This is actually an old version of For the latest and greatest, check out the new site.

Pipe Down

Any standards geek—such as myself—knows the value that lists can bring to your HTML arsenal. Most of the sites I design and build involve a lot of list manipulation. Learn to let ordered, unordered, and definition lists be your trusty sidekicks. Recently, I've been noticing a lot of list manipulation in other web standards sites, specifically for navigation. However, these sites sometimes contain different approaches to what I would typically do, and, more importantly, arguably go against what could be considered best practices. One of the most common examples is the use of the vertical bar, or the pipe.

It’s really a core supporting argument in the fight for separating content, presentation and behavior. (If you have no idea what I’m talking about, please check out Zeldman's awesome book, Designing with Web Standards.) Whereas the pipe is a great method to separate elements, it is a visual element and should be treated as such. Although it does degrade much better than most table-based navigation, including it in your markup is somewhat unfaithful to the cause. Here are some of my favorite variations that I often see in horizontal navigation schemes:

<li><a href="#">Home | </a></li>
<li><a href="#">About | </a></li>
<li><a href="#">Contact</a></li>

or, even worse:

<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>

If your navigation looks like this, don’t fret; there is a cure. Before we start, it’s important to note that there’s no such thing as “The Right Way”; it’s just a matter of preference, what you’re most comfortable with, and what makes the most sense to you. There are pros and cons to every approach, and this is certainly not an exception.

Let's start with a basic unstyled list, seen here. From here, there's just a couple quick steps to get this horizontal nav going and looking decent. First, let's get them all in a line using display: inline on the list items. I’ve also created some breathing room by giving each item some padding on each side. Less important, I’ve also styled the links with colors and a simple type treatment so we’re not staring at the default link color (not that there’s anything wrong with that).

Here’s where the pipes (or lack thereof) come into play. Instead of using them, I prefer using CSS-generated borders, seen here. Notice that, with borders instead of pipes, your separators can be a different color than the text. You couldn’t do that if the pipes were in your HTML without adding even more markup. Also note that you can use either border-right or border-left.

However, here's our first problem. By adding borders to every list item, the first item has a preceding border that isn't necessary. There are 2 major fixes for this, each having its own set of benefits and drawbacks. First, you could assign an id to each list item and override the style for the first element—Home, in this case—with border: none, as seen in this example. However, diehard semanticians would argue against adding markup to create a visual change.

The second approach involves using first-child, a CSS2 pseudo-class. I’ve added a rule that looks like this:

ul li:first-child {

That tells that browser not to render a border for any list item that is the first element (or child) of an unordered list. The example here shows the same result as the previous example without the extra markup.

Although this seems like a great solution, there’s always a stick in the spokes. The eternal party-pooper, Internet Explorer does not support CSS2 pseudo-classes, so only more progressive browsers will support this method and you may or may not choose to employ these methods, depending on how elitist you’re feeling at the time.

This just scrapes the surface of what you can do with minimal markup and handling all of your presentation with CSS. Mark Newhouse wrote a great article several years ago (2002) called Taming Lists that is still very applicable today.

To be fair, I’ve heard a very legitimate argument for using pipes in the actual markup for accessibility reasons, but I couldn't find much about it, so any extra information that you can offer is greatly appreciated. Hopefully, this gets you a little more excited about the strengths of CSS versus older methods.


Erik V. said:

Or, you could use li + li:before { content: " | "; }
but that might cause trouble, too!

Posted on November 1, 2005 01:04 AM

Niklas Steffen said:

IE again ruins that approach because it does not support the :before pseudo. At the moment I am still sticking to the Pipe, until IE decides to acquire proper standards support

Posted on November 1, 2005 05:23 AM

Andrea said:

I haven't liked using the pipe (as I once often did) since I've started using lists for navigation. Usually I have classes or IDs on each of the items in the list anyway, to enhance rollover or current states for the links, so it's fairly easy to tell the CSS to add a border:none to the first item in the nav. It may add some extra markup, but I've come across some really nifty uses for the IDs on list items used in conjunction with IDs on individual page IDs on the body tags.

Posted on November 1, 2005 10:04 AM

jordan said:

Isn't it rather typical of modern design to leave the bar before the first item anyhow?

For my part, I'm not so sure what the best method of dealing with the pipe would be--I'd probably just discard it and find another way to display the navigation.

This is very well-timed, though, as I've just begun work on a new version of my site, and will have to consider this question.

Just another thing to ponder...

Posted on November 1, 2005 08:02 PM

abba bryant said:

Or use javascript and something like jquery
to select the first element in the nav list and dynamically apply a class called 'first-child' to it.

this allows you to write the css :

ul li:first-child, ul li.first-child {

and then you don't have to worry about the css 2 idiocy in IE.

Posted on March 10, 2006 04:49 PM

Tim said:

Like Dan, I'm not a big fan of using pipes.
I'm using a quite simple, all CSS fix to this problem.
My li margin-right is 1px, and I use the background of the ul to fake a pipe (eg, black background generates a 1px black pipe)
Works well.

Posted on May 19, 2006 04:03 PM

Sorry: comments are closed.