Horizontal Rulez OK!
Hail the humble HR tag. These letters generally denote
'Horizontal Rule', but if you've ever grappled with styling it, 'Horribly
Random' might seem more appropriate.
The unfortunate part is that, as a structural layout widget that's
recognized by everything from Netscape 2.0, to PalmOS, to IE Mac, to
Searchbots, it should be very useful -- if only we had a little
control over its look and feel.
So, let's have a closer look at the lay of the land, before
investigating what we can do to improve things.
The first thing to know is this: If your design requires a thin milky
grey line -- one that closely resembles the scuzz that grows between your
bathroom tiles -- boy, are you in luck, mister!
The second thing to know is hardly any browsers agree on anything else
about HRs and how to render them.
Internet Explorer: All versions of IE (including IE5.2
Mac) seem to treat the HR as an opaque foreground element -- almost like a
flattened, inverted non-breaking space -- meaning you color it with
'{color: color}'. Borders can be applied to this object, and will
wrap around the outside of the line element. However, only
the Mac version runs any 'background-color' behind the border (i.e.
background-color will show through between each border dash).
Firefox/Moz: All Gecko-powered browsers, on the other
hand, seem to see the HR as the equivalent of a very thin grey DIV.
Following that logic, you re-color it using its background color:
{background-color:color}. Borders can be added to all sides, but
they will always render on top of that
background color (i.e. your background-color will show between each border
dash).
Safari & Opera: I've grouped these two because they
seem to take similar approaches to rendering the HR. Neither
'color' nor 'background-color' have any effect on their
default grey line ... at least, until you add a border, whereupon they
both suddenly acknowledge the background-color, and blot out the default
grey line. Go figure.
At this stage, it would seem that, with enough browser-specific hacks,
we should be able to select our own color, height and width for our HR.
Unfortunately, to me, that seems like a truckload of effort for what is,
ultimately, a very limited result. We need a more flexible solution.
Ok, maybe we could get full control over the look and feel by
using the 'background-image' -- perhaps a variation on the classic CSS 'image-replacement'
technique?
In a word,... no.
All versions of Internet Explorer tested attach a thin grey
'pseudo-border' to any background-image applied to a HR. Now the weird
thing is that this isn't the true CSS border property (marked by
an 'X' in the diagram) and, judging by my own and others' testing, cannot
be removed in any way whatsoever. It's a very light grey, but enough to be
extremely annoying.
Back to the drawing-board...
At this point, we're probably all coming to the realization that the
poor old HR is waaaaay out of its depth and needs a little assistance.
What if we were to wrap our HR in a DIV? We could still retain its
structural meaning within the document, but, with a little CSS to hide the
real HR, we can use the more robust DIV as the vehicle for our fancy line.
Non-CSS capable devices will ignore the DIV and render our 'old-skool'
HR.
The XHTML/CSS is pretty simple:
XHTML:
<div class="line"><hr /></div>
CSS:
div.line hr{ /* take out
the troublemaking HR */
display:none;
}
div.line { /* DIV that wraps and
replaces the HR */
background: transparent url(hr-3.gif)
no-repeat center center;
height: 30px;
}
Ok ... that's better than nothing, you're thinking, but it's pretty
clunky. You have to make sure all future HRs have the wrapping DIV or it
breaks!
Let's see if a dash of well-mannered JavaScript might do the trick.
Last year, Simon Willison wrote a very cool article on making
rounded corners using JavaScript. Without delving into the hardcore
JavaScript hocus-pocus, the underlying concept is pretty simple: send only
stripped-back, sensible mark-up to all browsers, but also include
JavaScript instructions on how an advanced browser might go about
'remodelling' our basic XHTML to allow for our more advanced rendering
tricks.
While Simon used this technique to add rounded corners to a box, we're
going to use something similar to wrap our HR.
In theory, simpler devices (old Netscapes, Palms, Lynx, etc.) will be
oblivious to these instructions and render our semantically perfect HR,
while more modern browsers will build the extra structure they need to
hang our fancier presentation on.
In essence, the wrapping DIV is nothing more than a figment of your
browser's runtime imagination.
Here's the function that you'll need to include.
function fancyRules() {
if (!document.getElementsByTagName) return;
var hr = document.getElementsByTagName("hr");
for (var i=0; i<hr.length; i++) {
var newhr = hr[i];
var wrapdiv = document.createElement('div');
wrapdiv.className = 'line';
newhr.parentNode.replaceChild(wrapdiv, newhr);
wrapdiv.appendChild(newhr);
}
}
window.onload = fancyRules;
I'm not going to do a line-by-line breakdown of its workings in this
newsletter, but I've commented the code here. In short, if
you include this function in your page, editing the CSS is all you'll need
to do to control the look and feel of your HRs.
Here's an example of the
code in action. View the source to witness the plain, old HRs in the
mark-up and, if you like, try disabling JavaScript to see how simpler
devices see the page. Selecting a HR in Firefox and selecting 'View
Selection Source' is the only evidence you'll find of the wrapping DIV.
All-in-all, I think this is a reasonably elegant and easy-to-maintain
alternative to a seething knot of CSS hacks, and the inclusion of a single
small JS makes this a worthwhile solution in many (but not all)
situations.
The previous 12 months has certainly seen a lot of new attention focused
on these kinds of unobtrusive JavaScript methods, and we're expecting that
to increase in the coming year.
In fact, we've almost completed the editing for SitePoint's DHTML Utopia
book, written by renowned member of the 'JavaScripterati', Stuart
Langridge. I read this title over the break and it is, quite simply,
awesome. Keep an eye out for it soon.
Simon, who 'tech-edited' the book, is certainly convinced of a coming
JavaScript renaissance. Read his thinking here:

