March 3, 2006
Pipe Dream
I just solved a CSS problem that's been bothering me for years: pipe lists. You know, a horizontal list of links separated by a "pipe" character, or rather, something that looks like a pipe character. My goal was to produce a pure CSS pipe list that works in IE5x/Win, doesn't use hacks, and dispenses with the leading left-hand border without additional markup.
Today a solution came together, but before I discuss the details, here's the fruit of my labor: the Luminous Pipe Dream (see example).
The Markup
There's not much to it: a ul wrapped in a div. But note the absence of classes or id's on the list items. That's what makes this a challenge.
<div class="pipelist">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
The CSS
Three simple rule sets:
.pipelist {
margin-bottom: 1em;
overflow: hidden;
width: 350px;
}
.pipelist ul {
list-style: none;
margin: 0;
padding: 0;
}
.pipelist li {
border-left: 1px solid #000;
float: left;
line-height: 1.2em;
margin: 0 .5em 0 -.5em;
padding: 0 .5em 0 .5em;
white-space: nowrap;
}
The Problem
Pipe lists are commonly produced as a series of links separated by the pipe character and are usually marked up in a paragraph, like so:
<p><a href="#">Item 1</a> | <a href="#">Item 2</a> | <a href="#">Item 3</a></p>
More semantically-minded coders mark up these links in a list and use CSS to present the list inline. The markup looks something like this:
<ul>
<li><a href="#">Item 1</a> | </li>
<li><a href="#">Item 2</a> | </li>
<li><a href="#">Item 3</a></li>
</ul>
The latter approach is better but still not ideal. The problem is the pipes. To my mind, pipes are presentational elements and thus don't belong in markup, but should be produced via CSS.
(Note: Some developers view pipes as content. This perspective hinges in part on the W3C's conditional recommendation to include non-link, printable characters between adjacent links. I disagree with this designation, but in the interest of staying on topic, I'll simply link to a thoughtful discussion of the issue at accessify.com.)
One thing's for certain: Whether you classify pipes as presentation or content, they offer limited stylistic options. You can control their color, but it's awkward to adjust spacing, difficult to manipulate height, and impossible to change width. In short, a pipe's presentational function is better served by the CSS border property. If this seems obvious, tell it to the folks who built IE5/Win, which doesn't support the border property on inline elements.
Fortunately for all of us, IE5x/Win is receding, day by day, into the oblivion it richly deserves. However, this hasn't stopped me from trying to produce a pure CSS pipe list that works in IE5x/Win, doesn't use browser hacks, and solves the "first-child problem" without additional markup.
What is the "first-child problem"? Glad you asked. Pipes (or in this case, borders) should appear between list links, not before or after the list as a whole. However, this is easier said than done, because a left border applied to all list items will produce a list-preceding border, while a right border will produce a list-trailing border. The CSS :first-child pseudo selector would offer a simple solution here, but tell that to the folks who built IE5-6/Win, which provides scant pseudo selector support.
What to do?
The Solution
I owe a debt of gratitute to someone named Fat Erik 5, for it was Fat Erik 5's approach, published at Max Design's excellent Listamatic, that pointed me to the answer. Fat Erik 5 (I'm not sure if it's proper to call him "Erik" or even "Fat Erik," so I'll stick with the more formal designation) used two pseudo selectors in his solution, neither of which are supported by IE/Win. Consequently, he delivered a workaround to IE/Win, using a browser hack to do so. It was Fat Erik 5's IE/Win workaround that got me thinking.
Fat Erik 5 applied a negative left margin to the list items, along with an equivalent but positive right margin, as well as equivalent right and left padding. Together these declarations serve to slide the entire list to the left, so that the first link aligns with the left-edge of the parent element. I used the same approach, as highlighted below:
.pipelist li {
border-left: 1px solid #000;
float: left;
line-height: 1.2em;
margin: 0 .5em 0 -.5em;
padding: 0 .5em 0 .5em;
white-space: nowrap;
}
If we stop here, we're left with a left-hand border sticking out into the alley. Not good. And since Fat Erik 5's workaround doesn't work outside IE/Win, I was forced to do some thinking of my own.
My breakthrough was to use the CSS overflow property to clip the overhanging border. Specifically, I applied overflow to a div, here called "pipelist," that contains the list. For overflow to work in IE/Win, I needed to assign a width to this containing div.
Here's the rule set for the containing div (note the two highlighted declarations, which serve to clip the hanging border):
.pipelist {
margin-bottom: 1em;
overflow: hidden;
width: 350px;
}
Note, too, the margin-bottom declaration. This gives the list a bottom margin, something that can't be applied to the ul itself, because of the way I've used floats. (The more natural approach—setting the li to display inline—fails to produce borders in IE5/Win, thank you very much.)
Also: The height of the border is controlled by the line-height of the li element. More line-height means more height, or taller borders. For what's it worth, I wouldn't set the line-height to less than the equivalent of 1.2em, as various browsers may clip away your link underlines.
A Variation: Centering the List
Unfortunately, the best method I've found for centering the Pipe List has several downsides:
- The markup requires an additional, non-semantic div
- The list fails miserably in IE/Mac
- The list as a whole is centered, not the individual list items within the list, which remain left-aligned.
- If the list exceeds the width of the containing element and breaks into two or more lines, the additional lines will left-align with the first list item.
That's a lot of downsides, but if you can live with them, the adjustments to the basic Pipe List are simple—just add an additional div and another rule set.
The revised markup:
<div class="pipewrap">
<div class="pipelist">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
The revised CSS:
.pipewrap {
text-align: center;
width: 400px;
}
.pipelist {
margin: 0 auto 1em;
overflow: hidden;
width: 350px;
}
.pipelist ul {
list-style: none;
margin: 0;
padding: 0;
}
.pipelist li {
border-left: 1px solid #000;
float: left;
line-height: 1.2em;
margin: 0 .5em 0 -.5em;
padding: 0 .5em 0 .5em;
white-space: nowrap;
}
Note that the .pipewrap width must exceed the width of .pipelist, or the list won't have anything to center itself within.
The Fine Print
I tested the Luminous Pipe List on the Mac in Firefox 1.5, Safari 1.3.1, Opera 8.5, and IE 5.2., and in Windows on IE 7.0, IE 6.0, IE 5.5, and IE 5.01.
Enjoy!
Update 4/18/07: Added white-space:nowrap to li to address some weirdness in IE when the list width exceeds the width of the containing div.
Update 4/19/07: Added instructions for centering the list.
Update 9/15/07: Revised centering instructions.
Published in CSS, Design, Markup, Web Standards
What Is This?
This is a blog about better websites—how they're made and what makes them better. Think of it as Apocalypse Now but with the word Apocalypse changed to Quality and the theme shifted from madness to best practices in web development. It's written by me, Michael Barrish.
Song of My Professional Self
I celebrate myself, and sing myself. I build bulletproof websites using web standards and related best practices. I work with designers and companies needing expert style and markup. Clear and sweet is my soul→
Weblog Articles
Latest
- Death of a Standardista
- I have no interest in building kick-ass containers for crappy content.
- Some Comments on Comments
- Why I dropped comment functionality.
- Great Copywriting—Not for Robots
- Neither for the faint of heart nor the narrow of mind.
- The Death of TimesSelect and the Future of Web Advertising
- There's a lesson in this, and it's not that information wants to be free.
Popular
- Adblock Plus Must Die
- An anarchist superhero comes from the future to rid humans of ads forever.
- Clients and Copy
- When the copy sucks, the website sucks.
- Pipe Dream
- I just solved a longstanding CSS problem: pipe lists.
- Confessions of a Bad Designer
- I'm a one-trick pony, and my trick doesn't necessarily work.
Duly Noted
Recommended reading.
- They Criticized Vista. And They Should Know.
- The documents include accounts of frustrated Vista users in Microsoft's executive suites.
- Lessons from the Book: Final
- I will no longer compensate for limited or broken specification support in browsers after January 1, 2010.
- 0 + 1307
- Sweetheart, that's all very nice, but if you're not going to eat pussy, you're not a dyke.
- Facebook's Brilliant but Evil design
- Facebook is now partnering with 3rd party sites and selling your information to them for money.
- Spammers Use Striptease to Crack CAPTCHAs
- A virtual stripper named "Melissa" that promises to progressively remove items of clothing for viewers who solve online CAPTCHAs is actually part of a scheme by spammers to crack web site registration traps.