Sentinel: Your Web-Performance Watchman

Create a centred horizontal navigation

Written by on CSS Wizardry.

Table of Contents
  1. Demo
  2. Update

N.B. This article is kind of old now. While the technique definitely still works, I’d recommend looking into Flexbox for this nowadays. Happy coding!

Need Some Help?

I help companies find and fix site-speed issues. Performance audits, training, consultancy, and more.

Centring block level elements is easy, just define a width and set margin: 0 auto;, but what if you don’t know that fixed width? You could use text-align: center; but that won’t work on 100%-width block-level elements either… that’ll only work on text-level elements.

Defining explicit widths and heights should always be avoided wherever possible, as doing so will make the document a lot less future-proof, flexible and extensible… Suppose you have four items in your navigation menu–you can work out the width of these and use margin: 0 auto; to centre them. Adding a fifth will increase the width, meaning you’d need to alter the CSS, too. This is far from ideal, and more so with a CMS to power the site (a client can add pages, but perhaps can’t edit CSS).

However, there is a way to have a centred horizontal navigation without knowing an explicit width, and without adding CSS. It’s also remarkably easy.

The markup:

<ul class="nav">
    <li><a href="/">Home</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/work/">Work</a></li>
    <li><a href="/clients/">Clients</a></li>
    <li><a href="/contact/">Contact</a></li>
</ul>

Pretty standard, an unordered list of menu items. The CSS is where it’s at. I have highlighted the bits that do the majority of the work:

.nav {
    border: 1px solid #ccc;
    border-width: 1px 0;
    list-style: none;
    margin: 0;
    padding: 0;
    text-align: center; /* « The magic. */
}

.nav li {
    display: inline; /* « More magic. */
}

.nav a {
    display: inline-block; /* « Last bit of magic. */
    padding: 10px;
}

What I’ve done here is simply create a navigation list and given it a border top and bottom (purely to highlight its centred text). Instead of floating the block-level <li>s left I’ve given them display: inline;, that is to say they no longer occupy 100% the available width and they now stack up nicely against each other.

Next we use (the much underused) display: inline-block; to make sure the links themselves don’t break onto new lines but still obey any padding values accordingly. Here I have given them a larger hit area by adding padding: 10px;

You could have, if you wanted, applied inline-block to the <li>s. however IE6-7 will only allow inline-block to work on elements that are inherently inline elements. display: inline-block; will not work on block-level elements.

Demo

Here’s a quick demo. Try using Firebug or similar to add other list items on the fly, and watch as they seamlessly centre in the list. I have tested this in IE7-8 to find it works perfectly. I haven’t checked IE6 but I imagine it’ll be fine.

Update

You asked and I heard; I have made a CSS powered dropdown version of this for you. The line top: 100%; will make the dropdown work in IE7, but kinda ruins the experience a little in all other browsers. Whether you leave it in or not is up to you. Again, view source for the how-to…



Did this help? We can do way more!


Hi there, I’m Harry Roberts. I am an award-winning Consultant Web Performance Engineer, designer, developer, writer, and speaker from the UK. I write, Tweet, speak, and share code about measuring and improving site-speed. You should hire me.

You can now find me on Mastodon.


Suffering? Fix It Fast!

Projects

  • inuitcss
  • ITCSS – coming soon…
  • CSS Guidelines

Next Appearance

  • Talk & Workshop

    WebExpo: Prague (Czech Republic), May 2024

Learn:

I am available for hire to consult, advise, and develop with passionate product teams across the globe.

I specialise in large, product-based projects where performance, scalability, and maintainability are paramount.