uwMike.com

I will be in Seattle in September, and back in Waterloo next January.

CSS Rulers

October 2nd, 2005

Nearly all webpages have a Top, a Bottom, and some kind of tile-able stuff in the middle which gives it all room to grow.

Once you try for a stretchy liquid layout, then it’s the same deal, except that the horizontal axis needs room to grow too.

The heart of liquid layouts is the Ruler. It’s a horizontal element which has one image tiled along it, and two more images stapled one at each end to close it off.

I’ve found various ways of accomplishing this simple task, so I might as well share a few. If I’m missing your favourite trick, let me know!

The Awful: A Three-Celled Table

This, of course, is the classical approach, here simply for the sake of demonstrating its absurdity.

<table width="100%" border="0" cellspacing="0" cellpadding="0">
    <tr>
        <td><img src="/wp-content/uploads/left.gif" alt="" /></td>
        <td width="100%" background="/wp-content/uploads/slider.gif"></td>
        <td><img src="/wp-content/uploads/right.gif" alt="" /></td>
    </tr>
</table>

It’s hideous, but like many table-based layout hacks, once all the elements are in place, it pretty much Just Works. Fortunately, we’re not going to be looking at it too much longer.

The Okay: Positioned Ends

Previous iterations of this site used a trick like this:

<div class="ruler">
    <b class="left"></b>
    <b class="right"></b>
</div>

Of course, it looks like nothing until we add some styles in:

.ruler {
    height: 3px;
    background: transparent url(/wp-content/uploads/slider.gif) top left repeat-x;
}
.ruler .left, .ruler .right {
    display: block;
    height: 3px;
    width: 20px;
}
.ruler .left {
    float: left;
    background: white url(/wp-content/uploads/left.gif) top left no-repeat;
}
.ruler .right {
    float: right;
    background: white url(/wp-content/uploads/right.gif) top right no-repeat;
}

What does it do? It has a container object with the slider image in it, and then the end-caps are floated to their correct positions.

And simple alternative to this approach is to position: relative the .ruler element, and then beam the endcaps into place with position: absolute. Both methods however, have this same weakness:

You can’t use transparency in the endcaps, since they’re laid on top of the background. I’ve covered up the effect in the demo above, by setting a background color on .left and .right, but look what happens when they’re transparent:

The tiled background is showing through the ends. In some cases, this won’t matter. In others, it’s a deal-breaker.

The Better: Onion Skinning

This approach has the same problem as the previous one, but it comes with a lighter markup footprint, and perhaps slightly simpler styles. However, unlike the above approach, there is no way to put background colours behind the end pieces. For this work, the endcap images themselves would need to be all solid pixels.

<div class="ruler"><b><b></b></b></div>

Two style hooks nested inside the .ruler. All we have to do is make all three nested elements the exact same size, and then using the background-position property, it will be easy to position our elements of imagery. Stacking markup to layer images can easily get out of control, but it can be elegant and sensible when used in moderation.

.ruler, .ruler b
{
    display: block;
    height: 3px;
    background: transparent url(/wp-content/uploads/slider.gif) top left repeat-x;
}
.ruler b {
    background: white url(/wp-content/uploads/left.gif) top left no-repeat;
}
.ruler b b {
    background: white url(/wp-content/uploads/right.gif) top right no-repeat;
}

Ultimately, this is still the same technique as “Positioned Ends”. It’s simply positioning the background, instead of positioning the element itself. But there are times when this is convenient. When the ruler is a title bar, and there’s to be other elements on top of it, it’s helpful to not have purely layout floats interfering with the works.

As with the above, there’s a problem that we can’t have end caps with transparent areas. So that’s when we bring the padding.

Update: Actually, you can, but the method is basically the same as “positioned ends.” You simply use negative margins or negative absolute positioning to draw the endcaps into their correct positions.

The Best: Padding-In

This approach is what I use currently for the top and bottom of this site. I wanted the ragged edges to show through to the wood behind, but I couldn’t have the ragged edge on the end show through to the slider.

It’s the same markup as Onion Skinning:

<div class="ruler"><b><b></b></b></div>

We simply reverse the order of the images applied:

.ruler {
    height: 3px;
    background: transparent url(/wp-content/uploads/left.gif) top left no-repeat;
    padding-left: 20px;
}
.ruler b {
    display: block;
    height: 3px;
    background: transparent url(/wp-content/uploads/right.gif) top right no-repeat;
    padding-right: 20px;
}
.ruler b b {
    background: transparent url(/wp-content/uploads/slider.gif) top center repeat-x;
}

Each element adds an image to the stack, and then uses its own padding to “push” the child elements away from it. This way, the sliding middle image is actually the innermost, rather than the outermost.

I like this technique because it’s rock-solid reliable, and both the markup and styles are pretty simple. Its main caveat is that padding adds to a specified width. So you can’t just set your .ruler to be width: 80%, because it’ll end up being 80% + endcap widths… at least, in everything but IE5/win. So if it’s to be centered or width-ed at all, it needs to be either pushed-in using margins, or wrapped.

At any rate, there’s one more thing to add to the mix.

The Cream: CSS Sprites

With CSS, it’s possible to combine multiple images into one. Why would you do this? Reduced number of requests drastically reduces the perceived load time for the user, and in many cases, reduces overall page weight.

The three images used up until now are GIFs, each clocking in at about 850 bytes. The images are so small that most of that is just header and palette in the file. When the three are combined into a single image, its size is just under 880 bytes! While the bandwidth savings may be negligible, it’s nice from the user’s perspective when graphical element “snap” into place all at once, rather than image-by-image as minute pieces trickle in from the server.

The markup is identical, of course, but the upgraded styles look like this:

.rule, .rule b {
    display: block;
    height: 3px;
    background: transparent url(/wp-content/uploads/ruler.gif) center left no-repeat;
    padding-left: 20px;
}
.rule b {
    padding-left: 0;
    padding-right: 20px;
    background-position: bottom right;
}
.rule b b {
    padding: 0;
    background-position: top left;
    background-repeat: repeat-x;
}

About Safari and Mixed Keywords: Shea’s description of CSS Sprites in the ALA article uses negative px values to “select” the desired image. We can’t do this because we need to be able to snap the right image to the right side of the div, and unknown pixel distance from the left side. And Safari botches up mixed units on background-position. What’s the solution? Use percentage values for both, or, as I have, use only three the same height and then go for top, center, and bottom.

Notes

I’ve used the <b> tag simply because it’s shorter and tighter than inserting spans. Since the bold-tag has been de-commissioned in favour of strong, why not take advantage of it as an inexpensive styling hook?

Regarding font sizes, IE has a nasty habit of expanding very thin elements to be the height of a line of text. Therefore, in all such elements, it’s recommended to toss in a little font-size: 1px or something similar.

So there’s nothing groundbreaking here, but it’s just a quickie reference for folks trying to know what to stick into a liquid design. The real trick, of course, is how to make images that easily tile and seamlessly join with other.

And I’m a whole lot less qualified to talk about that.

Mike

Leave a Reply

You can use Markdown for style. I love hearing from readers, but please don’t hijack the discussion, use offensive language, or try to sell anything.

© 2004-2008, Mike Purvis, some rights reserved. I'm running Wordpress, and I have an RSS feed.