Cross-browser List Delimiters

January 10, 2005

As XHTML is relegated to strictly a structural language and CSS is relied on more heavily for the layout and styling of the web's underlying markup, advanced uses of CSS are becoming commonplace. As nearly every web site has at least one set of navigation links, particular attention is given to styling the XHTML lists used for these links. Several insightful and comprehensive articles have been written on the topic, most notably CSS Design: Taming Lists, complements of alistapart.com. However, due to insufficient support for CSS2 in some browsers, namely IE, controlling these lists exclusively from CSS can prove to be challenging. This entry demonstrates a styling trick for horizontal arrangments that make use of a lesser known CSS property, clip, to supplement several shortcomings in CSS implementations.

One of the most common layouts for a list places the elements side-by-side in a horizontal configuration, possibly using delimiters to separate the elements. In an ideal world, CSS2 makes this easy by using generated content along with the :before and :after pseudo-elements. Assuming the stylesheet is already setup to layout the list in a horizonal arrangment, adding delimiters between the list elements can be done using the following CSS2-compliant directive:

ul li+li:before {
content: "| ";
}

Unfortunately, there are two problems with this definition, and both have to do with IE. First off, IE doesn't support generated content. Secondly, IE does not recognize the adjacent sibling selector, which applies the rule only to the elements that have a previous sibling.

There are several ways to make the horizonal layout with delimiters work in all browsers, but most of the solutions are dirty since they require a change in the underlying XHTML. While such a change is certainly not a crime, it does violate the goal of seperating the structure from the design. By no means should a CSS problem be of concern to the XHTML markup. Hence, there must be a better solution than having to add a hint, as in the following markup.

<ul>
<li class="first">one</li>
<li>two</li>
<li>three</li>
</ul>

I have discovered a solution that does not require such a hook in the XHTML code, making use of the clip property to truncate the leading background image of the first element.

It has already been pointed out that IE cannot use generated content, so the only way to create a delimiter is by using a background image. Therefore, the idea is to pad the left edge of each element to make room for a background image, serving as the delimiter. Next, by using the clip property, snip off the background image of the first element. This allows us to specify a delimiter between elements without having to make a change the underlying XHTML markup. Since the clip property can only be applied to absolutely positioned elements, the only requirement is that the list be positioned in this manner.

The relevant CSS for delimiting the list elements is below. A couple of live examples can also be viewed in the demo.

ul li {
padding-left: 15px;
background: url(delimiter.gif) no-repeat left center;
}
ul {
position: absolute;
clip: rect(0 auto auto 15px);
margin-left: -15px;
overflow: hidden;
}

Of course, the fact that the list must be absolutely positioned is a big but. In an ideal world, the features of CSS2 (generated content and advanced selectors) would be leveraged. However, until the time when IE is either overhauled or hauled out, such CSS workarounds are required.

This article has been written simply to present another option that may be considered when using CSS to style XHTML lists in a cross-browser manner.

Posted at 02:37 AM in CSS & Design | Permalink Icon Permalink

1 Comment from the Peanut Gallery

1 | Posted by xaga on February 15, 2005 at 02:41 PM EST

Thanks for a great tip. I would use it if it solved my problem too, but it does not: I want some generated content to appear on pages printed by my site's visitors, but the default setting does not print background images :-(