Building Great Nav Bars With display:table

In my opinion, website nav & toolbars should have somewhat of a native feel to them. Not necessarily native to your OS of choice, but built in such a way the user can hardly tell the app is a web app. A great example of this is Google Drive's text editor nav, and really most of Google's controls. Each time I use it there's a sense of solidity & responsive power that you just don't get from a lot of web apps.

Using display:table

There are a number of ways to lay out navigation. I'd say the most popular ways are setting a <ul>'s <li>'s to float:left, or using display:inline-block on them. I have found, though, utilizing display:table removes a lot of the hassle of formatting fancy navigation bars.

Basic SCSS

.navbar {
    display:table;
    li{
        display:table-cell;
    }
}

The HTML

<ul class="navbar">
    <li>
        <a href="#">
            Link
        </a>
    </li>
    <!-- 3x -->
</ul>

Here's the result of that markup:

Incredibly simple, no floats to clear, and no vertical alignment to dial in. It also gives you the ability to size your <li>'s in percents automatically. See the code below:

.navbar {
    width:500px;
    display:table;
    li{
        display:table-cell;
        text-align:center;
    }
}

Here we just set our <ul>'s width and the <li>'s follow suit perfectly. This makes for a great responsive nav bar that can break down easily at small screen sizes.

Using border-collapse & box-sizing

Since we're using display:table, we also have access to border-collapse just like we do when using HTML tables. Here's a great use case for collapsed borders:

.navbar {
    width:500px;
    display:table;
    border-collapse:collapse;
    li{
        display:table-cell;
        text-align:center;
        box-sizing:border-box;
        border:#888 1px solid;
    }
}

And the result (with some added styling):

Making It Feel Native

Again, not "native" to your operating system, but native to a user's expectation of interacting with web app navigation. When you use it, it has to feel like an extension of your mouse (or finger).

There are some special effects in play here. Lets notice the following: rounded corners (on the edges), collapsed borders in-between buttons, a box-shadow emulating a border on the whole <ul>, and the subtle white box-shadow creating an embossed look on the buttons.

Using border-collapse:collapse takes away the ability to use rounded corners on the element with display:table. The way to get around this is to instead use border-left and border-right, then use box-shadow to add the top and bottom. Coupled with using box-sizing:border-box, this makes for a very comfortable and customizable way to add borders & shadows without any overlapping border issues. Here's the code for that particular section (edited for brevity):

.navbar {
    display:table;
    border-collapse:collapse;
    border-radius:.25em;
    box-shadow:#d0d0d0 0px 0px 0px 1px;
    li{
        display:table-cell;
        box-sizing:border-box;
        border-left:#e0e0e0 1px solid;
        border-right:#e0e0e0 1px solid;
        &:first-child{
          border-left:0;
          & > a{ border-top-left-radius: .25em; border-bottom-left-radius: .25em; }
        }
        &:last-child{
          border-right:0;
          & > a{ border-top-right-radius: .25em; border-bottom-right-radius: .25em; }
        }
    }
}

Abandoning overflow:hidden

Often in navigation & toolbars you need to use dropdowns, tooltips, etc. and using overflow:hidden just isn't an option.

Notice the li:last-child and li:first-child selectors. What this does is remove the unwanted edge borders and gives us a nice rounded edge on the buttons. Another issue I run into often is having to use overflow:hidden to keep a:hover properties from escaping outside the border-radius. With this method, that's no longer a problem.

Adding a Dropdown

Adding in a drop down shouldn't be difficult, and shouldn't interfere with code around it or need much extra markup. Just as a proof of concept, and without going into much detail, the following markup can be used to create this:

The SCSS

/* inside the main <li> */
ul{
    position:absolute;
    visibility:hidden;
}
    &:hover ul{
        visibility:visible;
    }

And the HTML

<ul class="navbar">
    <li>
        <a href="#">
            <svg class="icon icon-calendar" viewBox="0 0 32 32"><use xlink:href="#icon-calendar"></use></svg>
            <span>Calendar <i>&#9660;</i></span>
        </a>
        <!-- Dropdown -->
        <ul>
            <li><a href="#">Child Link</a></li>
            <li><a href="#">Child Link</a></li>
            <li><a href="#">Child Link</a></li>
        </ul>
    </li>
</ul>

Browser support for display:table is actually quite good, and is honestly a joy to work with compared to using floats or inline-block. What do you think? Leave comments below or ping me on Twitter for questions & insults!

-Matt

Tweet