« Reading List: The Revolt of the Masses | Main | Reading List: Imaginary Weapons »

Sunday, June 25, 2006

HTML: Tiled Background Image Alignment

I'm currently preparing a new on-line book for the Fourmilab archives (it will be announced here when it's ready) in which I decided to use a background image to highlight certain passages of text. I defined the style for such text with a CSS specification like the following:
    .inveigh {
    	background-color: #FFEEB3;
	background-image: url(bgtile.png);
	color: inherit;
    }

(Specifying a “background-color” as well as the “background-image” causes the text to be highlighted in that solid colour even if the user has disabled the display of images.) For the background, I drew an image which would “tile” both vertically and horizontally, such as the one below:

Background tile image

and then I applied the style to the body of a paragraph with HTML code like this;

    <p>
    <span class="inveigh">
    Why dost thou converse . . .
    </span>
    </p>

When I viewed the page with Mozilla Firefox (version 1.5.0.4 on Linux), I was astonished and dismayed to see a background like that below, which I'm including as a screen grab image to avoid browser compatibility issues we'll get to later. (The quote used in this example is from Prince Henry's conversation with Falstaff in Act 2, Scene 4 of Shakespeare's Henry IV, Part I.)

Background applied to span

Yuck! Instead of the two-way cross-hatching you'd expect, the result looks like chevrons which don't even align from one line to the next. Stranger still, if I resized the browser window, the alignment would shift depending upon the width of the window. After verifying that the background image did, indeed, tile properly and trying lots of things such as different image sizes (my original images weren't a power of two in size, and I suspected that might be a problem), I also viewed the page with version 9.00 of the Opera browser, which is known for its CSS standard compliance, just to rule out the possibility of an obscure bug in Firefox or the Gecko rendering engine it uses, but Opera displayed the page with the same weird chevron effect.

After what would have been an extended bout of hair-pulling, had I enough hair remaining to pull, I discovered that Firefox and Opera render a background image differently depending upon the hierarchical level of the element to which the style is applied. Apparently, if you apply the style to an inline element such as “<span>”, the image is tiled on a line-by-line basis, but not vertically, but if the style be applied to a block-level element such as “<div>”, then it is tiled both vertically and horizontally to fill the entire box the element occupies. Changing the HTML to:

    <div class="inveigh">
    <p>
    Why dost thou converse . . .
    </p>
    </div>

results in the following display of the paragraph. (Note that due to nesting rules, at least in Strict XHTML 1.0, we must move the paragraph container inside the division, as opposed to the inline span, which is used within a paragraph.)

Background applied to div

Ahhhh…sweet planar tiling! Note that the background also now fills the entire box containing the paragraph, instead of extending only to the end of each ragged right line when applied using “<span>”.

Now if you're a grizzled Web page developer (which you probably are, if you've read this far), the question on the tip of your tongue is, of course, “What does Exploder do?”. Well, as is so often the case, Microsoft Internet Explorer, in both versions 6.0 and 7.0, behaves differently from the other browsers. In this case, it renders the background image tiled both vertically and horizontally, regardless of whether it is applied to an inline span or a division container, although the right margin continues to reflect the difference. This means that pages which use tiled backgrounds applied with “<span>” tags and tested only with Internet Explorer will “break” when viewed with other browsers.

If you'd like to test this phenomenon with your own browser, please visit this document which contains both examples shown above. If you observe any curious and/or interesting behaviour with other browsers, let me know with the feedback button and I'll report it here.

Update: Reader Lindsey observes that the “<span>” tag can be made to behave as a block-level element by adding a “display: block;” property to the style definition applied to the span. This works fine in Firefox, Opera, and Internet Explorer. Declaring the span to be a block-level element also causes the background to fill the box instead of appearing ragged right. I have added an example of such a declaration to the example document. Still, as Lindsey notes, it's better to apply the background style to an enclosing container which is a block-level element to begin with instead of forcing the browser to change the interpretation of an inline element to behave as a block. (2006-06-26 12:24 UTC)

Posted at June 25, 2006 21:52