A new image replacement technique
So, I was puttering around over at the CSS Zen Garden, marvelling at some of the designs, and then a thought occurred to me. While the Fahrner Image Replacement technique that is used there is a very handy trick, it does require special meaningless markup as a hook.
Just to refresh your memory, the Fahrner Image Replacement technique
works like this: you decide you want to replace, say, a header
containing text with an equivalent image. So, you wrap the text in a
span, hide the span with display: none
, and
set your image as a background-image
on the header. That's
it, as seen here:
<style type="text/css">
<--
// Hide the text in the header (which is contained in the span)
h1#firt span { display: none; }
h1#firt {
height: 35px; /* height of the replacement image */
background-image: url("hello-world.gif");
background-repeat: no-repeat;
}
-->
</style>
. . .
<h1 id="firt"><span>Hello world!</span></h1>
and it looks like this:
Hello world!
However, that extra <span> is rather a hack. Not only it is completely meaningless semantically, but, more importantly, you pretty much will only put it in if you know you intend to replace the display of that header with an image; if you didn't intend to do that then you wouldn't put in the span, and then later on when you did want to use the FIRT, you wouldn't be able to without hacking the HTML. Bah. There must be a better way.
And indeed there is. Instead of hiding the text in the header (which needs us to be able to address the text separately from the header itself, hence the meaningless span), let's just move it out of the way.
<style type="text/css">
<--
h1#newrepl {
padding-top: 35px; /* height of the replacement image */
height: 0px;
overflow: hidden;
background-image: url("hello_world.gif");
background-repeat: no-repeat;
}
-->
</style>
. . .
<h1 id="newrepl">Hello world!</h1>
Instead of setting our image height as the height of the header, we set that height in padding in the header. Then we set the height of the whole image to zero (so the header is only the height of the top padding), and hide the overflow (so that the text doesn't show, because it's outside the header's dimensions). And there you have it: image replacement headers without having to add a span:
Hello world!
Of course, it's never quite as simple as that. This
technique breaks in Internet Explorer versions less than 6, because of
its well-known mishandling of the box model; in particular, the size of
a box is computed as its width
plus its padding
, rather than the width
including the padding as its supposed
to. So we need to pass a different value to IE5 and IE5.5. The simplest
way of doing this is with one of the alternate box
model hacks, as follows:
h1#newrepl {
padding: 35px 0 0 0;
overflow: hidden;
background-image: url("hello_world.gif");
background-repeat: no-repeat;
height: 0px !important; /* for most browsers */
height /**/:35px; /* for IE5.5's bad box model */
}
So we supply the height of 0px as above, and then supply a height of
35px (the height of the image) for IE5.5. Note that the space between
height
and /**/
is
important.
And there we (really, this time) have it.
Summary
So, in essence, if you want to put an image in instead of an element (like a header), then add this to your stylesheet:
#ID_OF_ELEMENT {
padding: HEIGHT_OF_IMAGEpx 0 0 0;
overflow: hidden;
background-image: url("hello_world.gif");
background-repeat: no-repeat;
height: 0px !important;
height /**/:HEIGHT_OF_IMAGEpx;
}
Stuart Langridge, July 2003
Updates to the technique
- Firstly, everyone in the whole world mailed me to tell me that it broke in Opera because I missed out a comment. And Zeldman pointed it out too. Oops. My bad, all. Fixed.
- Seamus Leahy also came up with the same idea as me at the same time or so. Clearly great minds think alike. And he credited me before I credited him, so he gets the nice bloke award for the day, and I look like an insensitive heel because I was on holiday :-)
- On further research, Seamus was first, so nice one that man. I think it's a very nice technique indeed.