Unintentionally Blank

Phil Nash on the Internet, Web Standards and Accessibility

Image Replacement - Getting Closer?

Aug 31, 2006

by Phil Nash

Being relatively new to the web standards scene, and especially since I was drawn in by marvels such as the CSS Zen Garden, I have read over the many different ways of replacing text with an image. Time and time again I was disappointed with each method for one of two reasons; it used an extra empty span element or would not work in the "images off/css on" scenario. Using an extra span is unsemantic and "images off/css on" left a gap where either the image or text should have gone.

Can't CSS Deal With This?

Evidently not, otherwise one of the far more talented web developers out there would have already revolutionised image replacement and I would be using their method. However, whilst reading up about this the other day, I came across a rather hopeful sentence at mezzoblue.

The ideal fix is CSS3’s generated content module, which allows something like this:

h1 {
  content: url(image.gif);
}

I thought about this and did some research into CSS3 to discover that, for the most part, the generated content module was part of the distant CSS3 spec, but it could be used in certain circumstances. According to the CSS2.1 spec, content could in fact be generated when using the :before or :after pseudoclasses. This means that I should be able to adapt some code so that a standards compliant browser would be able to replace text with an image, but display the text if images were off.

To Work

I decided to work with my favourite replacement technique, the Leahy/Langridge method. Rather than pushing the text out of the way by padding the top of the element and applying a background to it, I thought I would push it out of the way with the image itself.

The Code

Given:

<h1 id="replace">Unintentionally Blank</h1>

You only need the following CSS to hide the text and display the image:

#replace:before {
 content:url(header.gif);
  display:block;
  }
#replace {
 padding:0;
  margin:0;
  height:104px;
 overflow:hidden;
  }

And here is an example. Note: 104px is the height of the image I'm using in place of the text.

What The Code Does

In the before clause we have two properties. One is our content generator, which is pretty self explanatory. Secondly we declare display:block;, this to make the image act like a block element so that it pushes the real text down.

Next we style the element itself. Declaring zero padding and margin is standard, the height should be the height of the image we are replacing the text with. Finally, we use overflow:hidden; like in Leahy/Langridges method, so that the text does not show. Perfect.

Issues

Firstly, I haven't got an extensive testing suite of browsers at my finger tips (if anyone does and wants to test for me, please go ahead), so the browsers I know this works in are: Firefox 1.5, Opera 9, Netscape 8. I am guessing that the very excellent Safari renders this well too. I can however promise that it will not work in any Internet Explorer version you can dream of. This is due to the lack of support for either :before, :after or content generation in CSS. Apparently iCab doesn't support those operators either (according to MacEdition), but I am only interested in the big four visual browsers really (plus, the degradation is certainly graceful).

Forgetting IE for the moment, I would like to focus on the accessibility and standards side of things. This method neither uses a meaningless extra element nor hides the text from a screenreader. So anyone can use it! Accessibility for all!

So It Doesn't Work In Internet Explorer?

Yeah, but what does? OK, not the right attitude, but until Microsoft start putting their software where their mouth is with regards to web standards, this sort of development is severly hampered. What to do then? There are two options:

  1. Style the text as best as possible and let it degrade in IE
  2. Give IE something else to do

Option one would stop me writing right here, but it doesn't seem to be the way forward, I mean you do have a reason for replacing the text with an image right? So to option 2, maybe we could just use one of the other image replacement techniques that already works in IE. I have already stated my feelings on IE's conditional comments so let's use them. I am going to use Leahy/Langridge, but feel free to replace their code with your own preferred replacement method. All I did was add:

<!--[If lte IE 7]>
<style type="text/css">
#replace {
  width:100%;
  padding-top:104px;
  overflow:hidden;
  background:#fff url(header.gif) no-repeat top left;
  height: 0px !important;
  height /**/:104px;
  }
</style>
<![endif]-->

to your head element. Note the use of the "lte" command in the conditional comment... come on Microsoft, you can implement the standards by version 8 can't you? Here's an example to check out in IE.

IE5/Mac?

No, it won't work on that either, but (if you're still supporting it) you could always pass your alternative method to it using the Band Pass Filter.

A Name

So what if this is the next image replacement technique? It'll need a name. How about Nash Image Replacement (NIR)? It fits with all the other names too, and it reminds you of me, perfect.

Conclusion

So, this method uses no extra mark up, does not hide text from screenreaders and displays the text if images are off but css is still on, in all but IE (I hope anyway, as I said, I have a very small set of testing browsers). So what next? All we have to do is sit back and wait for Internet Explorer to support the current standards and we have the method that we need. What do you think?

Unintentionally Blank is Phil Nash's thoughts on web development from 2006-2008. Any code or opinions may be out of date.