JavaScript Image Replacement

As discussed previously on A List Apart,
Fahrner Image Replacement (FIR), a technique developed to allow designers to use image-based typesetting while meeting accessibility requirements, only serves its intended purpose when screen readers misbehave.

Article Continues Below

The premise of FIR is simple: set the text-containing image as the background of an XHTML element and hide the corresponding plain text by nesting it in a span and setting the span’s visibility to hidden, or display to none.

Most screen readers, however, are clever enough to realize that text set to visibility: hidden or display:none should not be read.

That’s why Peter-Paul Koch came up with the idea to use JavaScript to replace plain text with image-based text (on the css-discuss mailing list), and that’s where the technique explained here comes in.

Why JavaScript?#section2

There are already many solutions to the problem, each of them using CSS to
hide, move, or stack the images and the text. The forum entries
related to Joe Clark’s FIR article propose several.

By using JavaScript, we have an opportunity none of these solutions give us:
the markup can be plain vanilla XHTML, with no need for any special IDs or
CSS tricks in it.

Non-JavaScript users will simply see the headlines as they are, and designers still have the chance to style the plain-text versions with CSS.

The only users whose experience is negatively affected are those
with JavaScript turned on and images turned off. These users will see the
text replacement for the image. An exception are Mozilla users — but more on that later.

Enough talk, show us the goods#section3

Take a look at the demo page and you’ll see the technique in action. This is achieved by using one script together with an array of image names.

replaceImages = new Array(
  ’About us|about.gif’,
  ’History|history.gif’,
  ’Contact Us|contact.gif’
  );function firdom(){
  if(document.getElementsByTagName && document.createElement){
    for (l=1;l<=6;l++){
      h1s=document.getElementsByTagName(’h’+l);
      scanandreplace(h1s,’h’+l);
      }
    }
  }
function scanandreplace(h1s,tag){
  for(i=0;i;
      if(thish1.firstchild.nodevalue==chunks[0]){
        newimg=document.createElement(’img’);   
        newimg.setattribute(’alt’,chunks[0])
        newimg.setattribute(’src’,chunks[1])
        // or newimg.src=chunks[1];
        }
      }
    }
  }
window.onload=firdom;

The array replaceImages needs to be defined either once in an
external JavaScript or for each page individually. It tells the script
which headline to replace with which image.

The text that will be replaced and the URL of the replacement image
are separated with a “|”.

In the below example, any headline with the content “About Us” will be replaced with the
image “about.gif”, any headline with the content “History” with
”history.gif” and so on.

replaceImages = new Array(
’About us|about.gif’,
’History|history.gif’,
’Contact Us|contact.gif’
);

All you need to know to use the technique is how to assemble this array. Then you can add the array to your page, include the script via its own script tag, and enjoy the graphical headlines.

If you are not familiar with the DOM and you don’t want to know about it, skip the next bit and proceed to “Where it fails.”

Under the hood — how it works#section4

So you want it more technical, then? Okay, firdom() does the following:

First we check if our browser can deliver what we need by testing for DOM
capabilities. This prevents old browsers from trying to do what they can’t.

if(document.getElementsByTagName && document.createElement){

Then we loop through all possible headline levels (<H1> to <H6>) and call another function, asking that one to find and replace all headlines with the current level.

for (l=1;l<=6;l++){
  h1s=document.getElementsByTagName(’h’+l);
  scanandreplace(h1s,’h’+l);
  }

This function, scanandreplace(), takes each one of these headlines and compares its content (the nodeValue of its first child) with the text preceding the “|” in each element of the array replaceImages.

function scanandreplace(h1s,tag){
  for(i=0;i;
      if(thish1.firstChild.nodeValue==chunks[0]){

If there is a match, we create a new image element and set its source to
the text following the “|” in the current element of replaceImages.

To take an additional accessibility precaution, we set the alt attribute of the new image to the text of the headline.

  newImg=document.createElement(’img’);   
  newImg.setAttribute(’alt’,chunks[0])
  newImg.setAttribute(’src’,chunks[1])

All that remains to be done is to replace the original text content of the
headline (its first child), with the newly created image — and voila, we have
graphical headlines.

  thish1.replaceChild(newImg,thish1.firstChild)
      }
    }
  }
}

Where it fails: Mozilla’s method of imageless surfing#section5

This technique works in every DOM-compliant browser. Without JavaScript, you
will see plain-text headlines (search engines will also see and index the plain-text versions). With images turned off, you will see the alt text within headline elements.

That is, unless you use Mozilla. If you go to Mozilla’s web features, you see an option that allows you to stop “loading images.” If you uncheck that checkbox, Mozilla stops loading images. Oddly enough, it does not
show the alt text either. This happens to every image, and also to
our little routine here. At the time of publication, we don’t know of any workaround.

Gimme gimme gimme#section6

You can download the script here. Watch its homepage for fixes and changes. Enjoy.

57 Reader Comments

  1. re: … Heilmann (write it any way you want)

    Sorry Chris… it was my lapsus kalamis.

    :: How could I answer to PPK’s claims if I didn’t get any?

    I meant on his post in ALA. When I first time read all (three days before) his replay were already here. Two days passed but it was totally ignored (looks like that yesterday).

    :: I like moose’s solution *** But what do you do now, when a client wants image replacement and it should work on IE5, 5.5 and 6?

    It is the question of web (web-publishing) understanding (imho): just to use scale-principe and to compare this: IE (x.yy) clients do not see the image but they have no any clue that image should be there – they just see the nice, real(!) heading (written by text and displayed by chosen style (font…)) which could be selected, copied etc… second case is that some other client, with strange browsing attitude (could browsing attitude be called as ‘strange’ at all?) means javascript on and images off doesn’t see the image, doesn’t see the real heading but see that ‘beautiful’ well known alt-image-replacement. So, I would not discuss in the field ‘What if…’ – just which of cases above author, you or anybody else, do prefer (maybe sometimes it depends on site content… maybe not). In moose case also, author do not need to write any of that meaningless warnings as ‘Headings on this site are represented by images…’ etc… means: ‘please do switch this or that on or of…’…

    :: I was more insulted by your post than by PPK’s to be truthful.

    Good. It was the base idea – to push you on some action.

    :: He claimed that the dash in his name is not much of an issue, you tried yourself on sarcasm about it.

    ppk has (c)opyright on his own name of course but has not (neither you) copyright on inappropriate using of any person name in global so, as long as I am protecting his name, I am protecting my own name also or anybody else’s in the future.

    :: PPK doesn’t need anyone defending him***

    The same as above: I do not know him really but I didn’t like the case. My small two cents for better world tomorrow if you know what I mean (I think you do).

    What I also think is that conflict is finished: you have nice attitude and ppk is also back when read your answer. Nobody knew that you really did everything on the correct way (pre-publishing issues) but ppk didn’t know that also:)) so: you forgive him, he forgives you and all ok.

    :: I respect PPK a lot, and I respect a lot of people knowing much of CSS to come***

    Somebody here mentioned that all of this is because you are not one from ‘big five’ (or ten or hundred) well known web-developers… it is not true: I do respect few well known people also (why should not) but I was really shocked when saw moose ideas; I’ve spent a lot of time browsing that site and sites of few of his friends. So fresh, so original… I mean we should respect work – not names only.

    Re: “I was more insulted…” I do apologize to you (so easy always to say that – never late) for your insulation but I can not apologize for my post. If you’d answer on ppk’s post faster, earlier, I’d never comment any article about javascript techniques (real amateur here – maybe just would post the moose solution link). So, Chris, I really want you to accept my ‘beg pardon’ and am sure that you will.

    At the end: I also can not understand people who are ‘abused’ with emotional ppk’s comment: sure that it had to be emotional – he did’t know that Chris wrote to him. At that time, his answer were so human, understandable, adequate… and good that Chris made everything clean.

  2. yes, I just this morning realised that the article has been published, as I spent the whole weekend with my girlfriend watching old Hitchcock movies as the weather was too foul to go out, and she doesn’t have a computer.

    Real life, sorry 🙂

    Generally I like PPKs new article a bit more, he could have taken in account the changes I made to the script on it’s homepage (as stated in the article, the place where changes will happen), but you cannot expect everyone to check all before publishing an article.

    I also cringe a bit at
    “Worse, by publishing such articles ALA actively promotes a sloppy, irresponsible coding style that sharply diverges from the accessibility, web standards and structural coding the magazine purports to promote.”

    As adding an invalid attribute is not web standards, sorry.

    One of the big advantages of my version (and I would gladly include the loading of the image bit that makes PPKs version superior – albeit I won’t until he agrees that I can do that) is that the markup does not need any specialities. This may sound anal about xHTML, but there is a reason for it:

    I was also doing this script as a client needed it. They want it, yes, they want graphical headlines, and search engines should find the headlines, and they want them all in IE 5.5+. Furthermore they want WYSIWYG editing in the CMS, which means we get after we run the tagsoup created by WYSIWYG through and XSLT sheet, clean HTML, but we have no chance to add ids or, for that matter, even invalid attributes. Reading the content of the H1 and generating an image file name from it is not an option either, as we are working in 12 languages, including special characters which could easily result in headlines getting the wrong image.

    Now, this is a big project, big money, and everything the client wants.

    One example where my script DOES make sense. Not everything the article claims it does, but it works.
    The client can happily edit their articles and they get an extra field to add all the images.

  3. >Generally I like PPKs new article a bit more,
    >he could have taken in account the changes I
    >made to the script on it’s homepage (as
    >stated in the article, the place where
    >changes will happen), but you cannot expect
    >everyone to check all before publishing an
    >article.

    Chris, I’m trying hard not to pick on you, but your comment is such a perfect handle for this important lesson that I couldn’t resist posting it.

    Publishing on a Serious Webzine: lesson 1

    If you publish so much as a word on a serious webzine like ALA, you *cannot go back on it*. Your article has to be perfect before you submit it.

    Chris, if you’d written your article anywhere else than on ALA I probably wouldn’t have noticed it, and if I had I’d have ignored it. I wrote my article solely because you chose to publish it on ALA (and because its editors chose to let it stand).

    I exclusively focus on your ALA article because ALA is a highly visible and respected webzine, and by default your article becomes highly visible and respected, too. It is this visibility and respect that I object to, and not the mere fact that you wrote your article.

    The next time you publish anything on a serious webzine, please make sure that it is perfect *before* submitting it, not after.

  4. I’m going to respond briefly to some comments made in this forum, and then I’m going to close the forum as it no longer serves as a calm or useful place for professional discussion of the ideas described in the article.

    Saturday morning I saw PPK’s first post (http://www.alistapart.com/discuss/javascriptreplacement/2/#c5727) and did three things in response:

    1. Article edit: linked to PPK’s current personal site, Quirksmode, per his suggestion.

    2. Article edit: corrected the spelling of PPK’s name, i.e. added the hyphen between Peter and Paul. PPK used to be an ALA author; I know how his name is spelled and would likely have caught the error if I had edited the article.

    3. Internal staff discussion: discussed PPK’s underlying point with the ALA staff and invited J. David Eisenberg (http://www.alistapart.com/authors/jdavideisenberg/) to join us as a technical editor in the areas of XML and the DOM — to which David graciously consented.

    http://www.alistapart.com/credits/

    David is a programmer, the author of a fine O’Reilly book on SVG, a co-founder of The Web Standards Project, and was a technical editor on my second book, Designing With Web Standards. His ALA bio page lists many of his past articles for A List Apart; more will be listed as soon as they are reformatted. David’s participation will help ensure that content quality in his area of expertise remains as high as ALA’s content quality in other areas.

    I considered these three actions an appropriate response: one that would make things better going forward. Anything else — such as responding in kind — I considered inappropriate.

    When we receive negative criticism, whether it’s discreetly handled in a private email message or posted publicly, and whether it’s delivered tactfully or not, we ask ourselves if there is merit to the complaint. If there is merit, we ask ourselves what we can do to improve. And then we take the necessary actions. And that is all that is needed.

    ALA tends to attract a considerate, professional crowd. Intelligent comments in the forum can be as useful and illuminating as the article to which they pertain. That is why we host a discussion forum.

    Our discussions rarely get hijacked and derailed, but if they do get bent out of shape, all we can do is shut them down. This forum is now closed.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career