CSS1 and the Decorative HR

Introduction

In the spirit of "graceful degradation", in the late 1990's I was looking for something that worked as a decorative rule on supporting browsers, yet worked like an HR on non-supporting browsers.

If you're in a hurry, you might just want to skip to the recipe at the end.

I rule out using IMG for this, because that isn't logically an HR. One possibility would be an OBJECT wrapped around an HR, but I still don't think that quite has the logical properties that I had in mind.

History

This page was started around the time of MSIE4 and NN4.* versions, and it tried to cope with some of the oddities of CSS support in those browsers. By around 2002 it was clear that simpler arrangements were sufficient if those older browser versions were excluded from coverage (i.e letting them fall back to the plain hr by one of the customary tricks for hiding critical CSS from older browsers). By the time of the last review of this page (2006) it is clear that this page should now be treated as being only of historical interest: there is no serious suggestion that these techniques are worth adopting now that adequate CSS support is widespread. See links to other pages on the topic.

Preliminaries

My general plan of attack was based using the CSS1 Formatting Model to define a "padding" area, having the desired decorative rule defined as its background image.

There are two kinds of image to be considered: a complete decorative rule such as:

[AIcons flowerpole]

(using no-repeat), or a small repeat image such as intended for tiling (repeat-x).

I'm defining coloured backgrounds, and using some images that have coloured backgrounds, in this article - it helps to see what's going on; but in practice one would probably want to use transparent backgrounds, and images defined with transparent backgrounds.

Note that in this article, I'm putting the styles directly onto the HTML tags that they affect, in order to make it clear what is doing what. Naturally, in the final design these attributes would be defined in a stylesheet, leaving just the simple HTML markups in the HTML document.

First attempt

The first plan was to have an HR with style properties that give it an appropriate padding and background, i.e something like:

background: color url(URL); padding: heightpx 0 0; width width;

Well, nothing much happened! When I started making some enquiries, I discovered that I wasn't the first person to have found problems with the HR, although Stephen Mack's stylebugs web page (URL now deceased, it seems) took a somewhat different approach: he expected to specify the "height" of the HR and get the background appearing within that, but it didn't. See also a mail thread from 1997 at www-style.

Second try: HR inside DIV

My second attempt was based on the idea of putting the HR inside a DIV, that would define the box within which we expect to see our background. Thus we have a DIV defined something like this:

background: color url(URL); margin: auto; padding: heightpx 0 0; width: width;

using the actual pixel width for the complete image (the flowerpole), and a percentage width for the tiled image (the footprints), as shown in the following examples


(this image has a non-transparent background, so it shows in its own colour, which happens to be light grey),


(this image has a transparent background, so the specified background colour, a light blue, shows through).

Both exhibit the following when viewed on both NS4 and MS IE4 (references to IE are to Windows versions):

Taking the last first, that is easy to remedy: specifying the style property "width:0" on the HR itself makes the rule disappear when stylesheets are active (obviously, we still want the HR to appear if stylesheets aren't active). Don't try getting rid of the HR by using "display:none": that results in the whole thing disappearing!!!

By the way, it's looking as if we need some vertical leading too, so we'll adjust that by setting a top margin. And another bit of fine-detail we might consider is that if image loading is turned off, but CSS styles are enabled, the HR would disappear altogether. Colouring the background leaves a rather unattractive plain coloured rectangle. Later on we'll specify a CSS border, which seems a reasonable compromise.

Now let's work on the height of the box. It might be thought that the superfluous height of the box is due to the implied height of the HR; however, explicitly specifying a height of 0 as a style property on the HR and/or on the DIV makes no difference to the display in either NS4 or MSIE4:


Perhaps the excess height is explained by the browser leaving room for a line of text? Hmmm, try configuring the browsers for different sizes of font and see if it makes any difference. Aha! On NS4, the height of the box grows and shrinks as one changes the font size in the browser configuration. Oho! On MSIE4, the box resolutely stays the same height.

Well, what about the "line-height" property, does that have any influence on the height of the box? Let's try setting it to zero (well, the W3C CSS checker doesn't allow a line height of zero, so we use a very small value instead).


In NS4, yes it does: setting the HR's line-height property near 0 causes the box to adopt its desired height, irrespective of the configured font size. In MSIE4, unfortunately, setting the line-height property of the HR and/or of the DIV seemed to have no effect on the extra height of the box.

OK, no matter what I did, MSIE4 seemed to be making the box about 16px taller than I wanted it to be, and I couldn't find any property to set to prevent it. In desperation, I set the padding to 16px less than I wanted (which produced the desired result on MSIE4), and then compensated by setting it in the line-height (which MSIE4 doesn't use). But this is a highly unsatisfying kludge!

Finally, why doesn't margin: auto cause centering? Well, the short answer is that those browsers failed to support the published spec, although some later browsers/versions do a better job.

Adding the somewhat implausible "text-align:center" to the DIV results in the things getting centered in NS4, but not in MSIE4, as with this example:


Another approach, that however is only applicable to the tiled image, is to specify explicit percentage margins instead of specifying width: here, for example, 25% on each side, leaving the remainder to be used as the (tiled) width:


Naturally, one worries that the fiddling about with padding and line-height pixel values will produce different results on other CSS-supporting browser/versions. I'm told it comes out a couple of scan lines too high on Mac MSIE 4; there's a hint of the same effect in Opera 3.50beta.

OK, time to tidy up a few ideas. When we add that border mentioned above, MS IE increases the height of the actual image again, so we play around with the padding and line-height values yet again:


Centering non-repeating images remained a problem. Other suggestions that have apparently brought relief in other situations, e.g putting "display:inline" on the HR, did not help further. The only approach that brought genuine relief was to put the DIV inside of another structure that had the text-align:center property. Well, unless the BODY has this property (which would be rather inconvenient), that means putting the existing structure inside yet another layer of DIV, which I find unsatisfying. Oh well, for the purposes of completeness, here's the flowerpole done that way:


Conclusions

This is the best recipe I have found so far, that works with version 4 of the Big Two and falls back gracefully to a plain HR on pretty much anything where the decoration doesn't work. It's subsequently been observed to work also in MSIE5 and in a snapshot (late May'99) of the Mozilla development, and in various versions of Opera.

The following stylesheet (I've called the class "dr" for "decorative rule", but the name is of no particular significance) could be used, with or without the default background image:

    .dr { background-image: url(what.ever);
          background-repeat: repeat-x;
          margin: 1em number% 0;
          border: 3px double #999999;
          padding: (height-16-2*3)px 0 0; 
        }
    .dr HR { width: 0; line-height: (16+3)px }

I've shown how the arithmetic works, but of course you have to evaluate the answers and put that into your style sheet. Specify also a background-color if you wish.

You would then call this out in the HTML with:


In order to use different images on different occasions, they could be specified explicitly in the STYLE attribute of the DIV, like this:


If the images are of different heights then of course you'd have to specify an appropriate padding-top on each DIV's STYLE attribute.

If you want to use a single image (like the flowerpole) rather than a tiled repeat, then I didn't find a better way than the rather clumsy double-nested DIV shown above, unless you want to rely on margin:auto being supported.

In early 2001, an email from Jeremy Parsons reported as follows: this is for a single image, rather than a tiled repeat. (I notice that this uses auto for the left/right margins?- something which I had avoided at the time I wrote this page originally, due to lack of support in the then-current browsers.)

MSIE 5.0 for the mac apparently ignores width on the HR but still obeys margins, so...
.dr
{
        text-align: center;
        background-image: url(images/bar.gif);
        background-repeat: repeat-x;
        margin: 1em auto 0;
        padding: 1px 0 0; /* 17-16 */
        width: 496px;
}
.dr HR { width: 0; line-height: 16px; margin-right: 100%; }

Note on MSIE 3 versions

The techniques described in this note don't seem to do anything useful on MSIE 3 (various versions), although they do degrade gracefully to horizontal rules of various widths.

However, another effect is seen: the browser invents some bogus URLs which it tries to retrieve from the server, causing pointless network traffic, and clutter in the server's error log. It's clear that the browser is creating these bogus URLs based on a misunderstanding of what it's finding in my DIV STYLE= attributes: presumably, if the styles had been put into a stylesheet, instead of being provided here in-line, the problem wouldn't have arisen.

Caveats

This technique was based on experiments with actual browsers, and therefore may well fall down in some way with different browser versions. Braden McDaniel points out an inconsistency with the CSS formatting model in relation to floated elements:

The canonical behavior of HR does not match the CSS notion of block display as far as floating elements are concerned. Floating elements float "over" blocks, while horizontal rules have historically contracted to fill the space left vacant by an element floated left or right. So in the presence of floated elements, a DIV won't (or at least shouldn't) behave the same as a HR.

Rick Parsons notes in relation to this issue that one may need clear: both to stop the rule from cutting across a preceding image.

And in my experience it doesn't work on WebTV/MSNTV, but I made no attempt to fix that. The WebTV viewer makes rather a hash of this page, apparently letting centered alignments "leak out" of divs which have been closed, and producing erratic left margins and such. (This report with MSNTV viewer 2.8).

Other page(s) on the topic

http://www.sovavsiti.cz/css/hr.html

And diveintoaccessibility discusses good compromises which work for more-recent browsers, and fall-back to a plain HR on older ones such as Netscape 4.

Or even, this site merely styles the HR itself.


|Up|?|RagBag|About?the?author|