Web Bout

Web Bout

Image Replacement Revisited

By Charles J. Conrad

Nothing like beating a dead horse. Wait … He's still breathing!

As I was developing my web site, I decided I wanted to use some sort of image replacement for the main title(s) of each page. This decision was pure fashion: to give my pages a refined elegance and, by some convoluted, imaginative psycho-babble extension, a better impression of me. It was not motivated by some bandwidth hogging conspiracy, although that would undoubtedly be much more interesting and result in traffic overload on my web site.

As I looked through past articles and discussions on this topic, I was struck by the considerable activity in the past and the apparent lack of activity in the present. Most of the comments on published articles were closed. Obviously, this must mean that the whole point is settled; I only needed to implement the winning approach. Now, exactly where is that winning approach? As I tried to reconstruct the history of the subject, it seemed that there were two basic camps: CSS-based and JavaScript-based. Some of the CSS-based approaches had been thoroughly critiqued, and, to be honest, I didn't like any of them anyway. That left the JavaScript-based techniques (JIR, for short). Yes, I know, there are also the Flash-based techniques, but I'm not interested in those either. With apologies to Thucydides, here is my brief version of the history.

The main contributor appeared to be Peter-Paul Koch (http://www.quirksmode.org) with the following articles:

The other contributor was Christian Heilmann, who wrote an article for A List Apart #164:

Of course, article [2] jumps out at you, doesn't it. After reading this savage attack (his words, not mine), I don't think I want to get on his bad side. Oh, you web developers are such a brutal, cantankerous lot! Maybe I should become one!

I love reading a good tirade, but I won't dwell further on these contributions. Clearly, I have built on them and proper credit needs to be given. Because I was not completely happy with either of them, though, I decided to write my own. Which leads me to this article.

The general idea of searching the document tree and looking for the right tags to replace seemed like a good approach. I was only interested in replacing selected <h1> tags, typically one per page. The idea of storing the file name of the replacement image as the id of the tag also made sense. Ideally, I would prefer to store the complete path to the image, but "/" is not a valid character for an id name (even though some browsers support it - I tried it). However, "." is a valid character, provided it is not the first character, so it is possible to store the file extension and thus have more than one type of replacement image file. I tend to use .png, but support for .jpg and .gif is desirable. Since the complete path can't be stored in the id, I put all the replacement images in a common directory (/images/titles/) that is also defined in the JavaScript. I played around with an alternate approach of storing the complete path with character substitution, like substituting _ for /, but I didn't like it and having a common directory for the replacement images in not a huge inconvenience.

I also wanted to add a class name to the <h1> tag, for two reasons. First, I wanted to pattern match against the class name for replacement. Second, I wanted to give the image a class that I could then use in conjunction with CSS for more precise control, such as positioning. The pattern I used was "title*", but obviously, it could be anything. In order to perform image replacement, the class has to match the pattern AND there has to be an id. If these conditions are met, the text is replaced by the image, with its class tag set to the same class, its id tag set to the filename and its alt tag set to the text that was replaced. The original html looks like the following:

<h1 class="title1" id="Home.png">Home</h1>

Replacement is equivalent to:

<img class="title1" id="Home.png" src="/images/titles/Home.png" alt="Home"/>

I also have the following CSS:

/*** Replacement images ***/
img.title1 {

In terms of implementation, I really didn't like the test loading of a timestamped image as described in [1]. Based on his comments, I don't think the author liked it either. I took a different approach. First, I test for DOM using a standard approach:

/* Check for DOM support */
    if (!(document && document.implementation && document.implementation.hasFeature))

No DOM support means no replacement. Next, I check for image support using a standard approach:

 /* Check for image support */
	if (!document.images)

No image support means no replacement. Next I look for <h1> tags with matching class names. If a match is found, image replacement occurs if the id is not null (test not shown here).

	var pattern = /(^|\s)title/;
	var titles = document.getElementsByTagName('h1');
	for (var i=0; i < titles.length; i++)
		if (pattern.test(titles[i].className)) 

Now for the arguments, fights and, if we're lucky, maybe some tantrums.

What happens if …?

  1. If the browser doesn't support JavaScript or has it disabled, the original text remains.
  2. If the browser doesn't support DOM, the original text remains.
  3. If the browser doesn't support images, the original text remains.
  4. If the browser supports JavaScript and DOM and images, but image display is disabled, a blank image box with the original text is displayed (now the alt text), just like all the other images on the page. A screen reader will correctly read the alt text to the user.
    Note: Some browsers apparently return true for !document.images when image display is disabled. This is perfect - the original text remains.
  5. If the browser supports JavaScript and DOM and images, and has image loading enabled, a pretty image is displayed, suitably tweaked by CSS.
  6. If the browser supports JavaScript and DOM and images, has image loading enabled, but does not support CSS or has it disabled, the image may not be positioned exactly. That is fine, since nothing else will be positioned correctly either.

If you are not of the class brutal savage, you may even see an example on this page. For those of you interested, the source can be downloaded here replacetitles.js and may be freely used, modified and redistributed.