Skip to: Navigation | Content | Sidebar | Footer

Weblog Entry

Image Replacement. Again.

March 30, 2005

Since there are still lingering questions about image replacement, this is the state of CSS image replacement in early 2005.

In the past few weeks, I’ve had some conversations about image replacement techniques. A quick recap for those who may not be familiar: image replacement is the concept of taking a structural, text-based HTML element (an h1, for example) and substituting it with an image. Why do it? Better typography and more visual interest, as well as flexibility in the CSS to later change the images themselves. Why not do it? It’s hackish, somewhat inaccessible, and the old ‘non-web’ argument applies to any instance where you’re locking text up in an image.

Of course, a few years ago I was keeping a tally of all the various ways of doing it. And we all know about sIFR. So I don’t have to summarize those here.

One of the more popular questions I’ve been answering regards which method I use. Since Douglas Bowman officially deprecated the original FIR (Fahrner Image Replacement) that he popularized a few years ago, it’s been necessary to choose from the list of other techniques, of which there are many. Heck, a brand new technique just showed up the other day, even.

So which do I use? I’m still not going to say just yet. Let’s talk about a few more things that influence the decision first.

Classic FIR had three problems: an extra span in the markup, some screenreaders would ignore the hidden text, and in a scenario where a user had CSS enabled, but for some reason had turned off images, they wouldn’t see anything. As of this writing, all problems have been addressed in one technique or another, but there is still a decision to make between trade-offs, since no one technique does it all.

The Mike Rundle/Phark method and the Gilder/Levin method demonstrate this trade-off nicely. One elegantly and simply hides the text in an accessible way to everyone except those with images off and CSS on, the other solves that particular problem with plenty of ugly code.

So the temptation is to discount the images off/CSS on scenario as unlikely, and use the elegant solution. Except that it turns out there are quite a few instances where this scenario may be more widespread than it first appears. Dial-up users, of which well over half of all web users currently still are, have limited bandwidth. They may end up turning off images in their browser for the sake of quicker load times. Or even if they don’t, all dial-up users are still at least temporarily affected by this problem during page load, and no text equivalent for the images can be annoying, to say the least.

Finally, it’s possible that the user hasn’t made the choice at all, but it’s occurring anyway. Recently I was asked about a Windows accessibility setting that throws the entire OS into high contrast mode. A peculiar side effect was that in Internet Explorer, all background images were ignored while in this mode (although foreground images loaded fine.) And there are no doubt scenarios I’m not accounting for here, so yes it’s likely that the images off/CSS on situation is affecting users.

And targeting no one particular method, what about Google? Let’s face it, when you’re able to place text in a page that won’t be displayed to the viewer, through substitution or some other method, the potential for SEO spam is ripe. The same holds true across all image replacement techniques, sIFR, and hey, even alt text for that matter. We have to be prepared for the worst, but the chances of Google blocking legitimate sites that have been using these techniques for years — simply to punish SEO spammers — is slim. It’s probable that they would block the elements themselves (instead of the entire page/site), or even more likely, that they would treat the hidden text the same as they would any other textual content, and filter it on its merits.

In any case, the methods we have are imperfect. The ideal fix is CSS3’s generated content module, which allows something like this:

h1 {
  content: url(image.gif);

The W3C CSS working group is aware of the accessibility issues of current FIR variations, and last time I checked in they had properly accounted for fallbacks in situations like the images off/CSS on scenario.

But until such time as CSS3 is supported across enough browsers that we can use this method, we’re stuck picking and choosing between imperfect methods. And getting around the basic accessibility problems, there are even more issues. Rundle/Phark breaks in Win/IE5 in certain situations, while Gilder/Levin basically disallows the use of transparent GIFs due to the fact that the text will peek through the transparent spots.

Aware of its shortcomings, I continue using the Rundle/Phark method. I don’t necessarily think it’s the best choice for all users, and I’d happily ditch it for a more robust method like the CSS3 generated content solution. Why not Gilder/Levin? To get it truly cross-browser compatible, you have to do this. Again, it’s a matter of deciding between trade-offs.

Turnip says:
March 30, 01h

Test there a name for the method with padding that Rob talked about? (

What are the issues with it? (Apart from being able to select the text downwards - although this doesn’t happen in Opera, and IIRC, it doesn’t happen in IE either.)

Turnip says:
March 30, 01h

Oops… sorry, where it says “Test” it should say “Is”. The commenting was slightly buggered and I was playing around trying to get it to work… then I forgot to get rid of it ; ).

AkaXakA says:
March 30, 01h

That MIR method sure does look promising!

I’d say sIFR and the MIR method are the way to go (and don’t get me started on the img-off+css-on debate: no user truly surfs the web that way. period.).

But what’s the point you’re trying to make with your article Dave? That until CSS3 is supported there’s not going to be a “clean” way of replacing text?

March 30, 01h

> no user truly surfs the web that way. period.

Really? So that must mean that Dave is lying in this post then right? With all his experience, when Dave Shea says that there is a percentage of users who browse with Images Off/CSS on, then I would take it for the truth.

If I was a dial-up user, I would probably turn images off if I was doing a lot of surfing around. That doesn’t mean I would go through the trouble of turning CSS off too, I don’t even know how you would do that in IE.

I would be more shocked to see vistors with CSS Off/Images Off than anything else.

I am sure Images Off/CSS On people are quite used to websites not looking too good under this scenario and they are probably fully expecting it, but I know that’s a cop-out ;)

Oliver says:
March 30, 01h

Soon, fonts supported by browsers will be widened to the point where we don’t have to use images anymore. But that raises issues about the operating systems..

Dave S. says:
March 30, 01h

“With all his experience, when Dave Shea says that there is a percentage of users who browse with Images Off/CSS on, then I would take it for the truth.”

Well, in general you might want to exercise a bit of discretion. I can be wrong too you know… but in this case, yes, I happen to have experience that says a small percentage of users *do* browse with images turned off. It may be remotely small, to the point of irrelevant, but I’ve listed two potential scenarios in this article (and I’m sure there are more).

“Soon, fonts supported by browsers will be widened to the point where we don’t have to use images anymore.”

Sorry, but… what? What are you basing this on?

Pascal says:
March 30, 02h

Why not implementing a alt-attribute for background images? Would solve a wide array of current accessibility/IR problems, i guess.

March 30, 02h

Pascal - the point is that alt attributes hold no semantic meaning, therefore screenreaders do not know whether an image is the logo of the entire site or just an email icon. Attaching semantic data to the information (the same way sighted users can see larger text and assume it’s more important) is the goal.

And thanks for pimping my technique ;)

Rene Enguehard says:
March 30, 02h

“Soon, fonts supported by browsers will be widened to the point where we don’t have to use images anymore. But that raises issues about the operating systems..”

I don’t see how that can be true. Sure browsers will accept more and more different alphabets and whatnot (heck, they already accept any major ones), but fonts are something else.

Most major corporations have their own trademarked font. Some companies I have worked with required all the headings to their printed material to be in a particular, proprietary, font. This issue could not be addressed for the web however and it’s not because all major browsers will widden their font lists that we will be able to accomodate particular fonts.

Basically, until the big browsers and the W3C sit down and iron out a way to append fonts to a page, this will still be an issue. Maybe not for the average Joe, but still an issue for any professional website.

Trovster says:
March 30, 03h

I have to say I originally used FIR but have latched onto and stuck with the gilder-levin technique. Although the extra mark-up is a pain and leads to some redundant code the method is good with images-off/css-on and I think this is why it’s the best IMO. The other fall-back is the lack of support for transparent images. Bit of a problem, but I’ve rarely come across it as a major stumbling block.

I have seen some good methods which use :before to put the image before the text, then overflow: hidden on the element with a fixed width/height of the image. Works really well. Now we just need the browser support!

March 30, 04h

I usually use the SIR technique, as it caters for the images off/CSS on issue as well as just about everything else. I have no problem with adding an empty SPAN, because the SPAN tag is meaningless, so it’s like having whitespace there instead. I’ve never heard of anyone having problems with it, so even though it’s not entirely elegant, it’s much nicer to add an empty span than a ton of other crud.

But hey, if you really don’t want to have an empty SPAN, you might check out BIR - yes, another image replacement technique. In the event that your header is a link, there is no requirement for an additional SPAN tag; if your header isn’t a link, though, you have to wrap the text within the A tag in a SPAN. Unfortunately, neither Bob nor I is a Mac user and as a result we haven’t been able to test this for any problems in IE5/Mac or Safari. (If anyone sees a problem with it in Mac, please post a comment on Bob’s blog.)

March 30, 05h

Maybe I’m just shooting off at the mouth here but…

Why do screenreaders even bother to load the CSS? I know they’re based on top of other browsers, but I think it’d possible to, programatically, tell IE not to load stylesheets. Surely it’s possible to adjust FireFox to behave in that manner?

CSS makes it easy to provide alternate stylesheets, why not provide an alternate for people who need to cut down on the bandwith? (And make sure they know of said stylesheet)

And what about an alternate stylesheet, e.g. media=”reader” (!=aural). Or have a JavaScript check for ‘images on’ and overlay the ‘fancy’ stylesheet.

Something to look into maybe? More interaction with the developers of screenreaders would me more than helpful.

P.S. : I’m pretty sure you will have noticed by now, and if not please don’t hate me for pointing it out. There’s a duplicate ‘note’ on pages 132 and 133 of your (wonderful) book.
Incidentally, it’s the note describing screenreaders.

March 30, 07h

Why do screenreaders even bother to load the CSS?

You know, maybe that’s something we haven’t been complaining about enough. It just goes to show that not many of us care about those who actually depend on them.

For the last 3 years we’ve been complaining about all the horrible things with IE6… what about the things that went wrong with screen readers… why won’t JAWS make an update?

Is there even a population out there that uses screen readers that pay attention to the “look” of the page…

oh wait, my bad (just realizes this), there are css rules that apply to speaeh…

okay well couldn’t it just ignore all the rules that have nothing to do with speech?

Bob says:
March 30, 09h

Thankyou for another plug, Jonathan. Actually, you need a span for the link to work. And thanks to a visitor, I now know it works in Safari, Camino, and Firefox on Mac. IE/Mac shows like images were turned off. So I thank you!

Enough of me syphoning Dave’s fame. You need an extra element for reliable image replacement. CSS 3, when supported, will solve many issues.

Al Abut says:
March 30, 11h

As far as I understand it (I haven’t been using it) sIFR seems to handle all three problem scenarios - do you have any problems with using that, Dave? Or is it just a general uneasiness with anything overly Flash-based? Because I was in that camp until Mike D explained that it degrades just fine in Flash off/Javascript off situations:

Better yet, the titles are made dynamically, without having to create all of those tedious images by hand - that’s one in the plus column that none of the other techniques have.

March 30, 11h

sIFR “doesn’t” fix all the problems. My solution (if implemented by browser makers) would be the best bet.

What sIFR does is that if no javascript XX Flash are not found, it defaults to CSS…

Well then, the problem relies with CSS like I was saying earlier, if we could have something like


I think the world would be a better place (Hypothetically).

Regardless of all that anyway, still, the benefit of image replacement (over any plain typography method) is that you can use “image”ry - may that be all your “J“‘s turned into flowers or the dot’s in your lower case i’s turned into apples. You can do so much more with imagery over plain type (even if you could choose any font from your library).

Mike D. says:
March 30, 11h


There are still certain instances where standard image replacement (whatever-I-R) is better than sIFR. For instance if you need Photoshop- or Illustrator-level control over your type, you still have to use images. Whether that be for kerning, blurring, or the use of other graphical elements. With (non-automated) image replacement, you can replace type with just about any graphic you want. With sIFR, you are pretty much just replacing crappy type with much better type. You don’t have a ton of control over it after that though.

March 30, 12h

I do believe that I saw a stylesheet the other day that had content: url(); plus the Rundle/Phark method. I also dig the padding-top variant[1].

Being the prometheus of the gang, I always tend to ignore everything <=5, and many hate me for that ;)

1: h1 {
height: 0;
padding-top: 100px;
background: url();
overflow: hidden;
But people find this scary, as you can select the text by dragging down on the element.

March 30, 12h

Gosh, until now, I haven’t realized that there are truly numerous ways of image replacement. After seeing the headline of this post “Image Replacement. Again.”… Those were exactly my thoughts as well. I mean really, Again?

However if you really look at the progress of the way things are moving, I think we’ll be saying this for a while. To truly have control over our own typography, we’ll need something better than even what CSS3 currently has to offer. Something more like a font plugin. Or maybe CSS will implement something like

font: url(/fonts/spiffy.ttf);

Of course we still get into Copyright laws and misuse. Even if you bypass all that, I’m sure the web will go through a wave of people using horrible font selections for their site….thinking that just because “we can,” doesn’t mean “we should (use that font).”

March 31, 01h

For what it’s worth, I spent the last two years doing all my browsing from home with only a mobile phone as my modem, paying per megabyte. It was very slow and very expensive so I would always have images switched off, but CSS on. When I found a site that was using an image replacement technique, I tended to just switch CSS off as well if it was necessary - just the click of a button in Opera.

Jim says:
March 31, 03h

Remind me again what the real problems are with img elements and alt attributes?

It seems to me that the only real drawback is that the URI to the image is contained in the HTML rather than the CSS.

That I can live with. Things breaking for visitors in the myriad ways discussed here, I can’t live with.

If you have to worry about what happens when something is disabled, then the image is *part of the content* and should be in the HTML.

The alt attribute is an alternative representation for the image, should it not be displayed. That is its semantics. It is not true that the alt attribute has no semantics; they are clearly defined in the HTML specifications.

The mechanisms people discuss here seem to be little more than wheel reinventing. Clever hacks, but hacks nonetheless.

March 31, 05h

You can allready use the content-property combined with the ::before- and ::after-pseudo-elements.

IE don’t support it, of course, but we can use the IE7 JavaScript-library to enhance the support.

March 31, 06h

I think your missing the point, sure alt text helps give meaning to an image of text, but what the real problem is is when you want to use an text image as a header. Sure you could do it the img alt text way, but that won’t give proper structure to the page like a header tag will. It would be nice if you could just put header tags around the normal text image and use alt text, but that doesn’t cut it semantically or for accessibility.

For Accessibility purposes (this means making it accessible to people with and without disabilities - whether they are say blind, deaf, etc. or just want to see the page on their PDA) you want to make sure you use correct semantic markup and make sure to use it in places where it is supposed to be, like using header tags where there is a header in the document. That way you are giving meaning to your document structurally and not just visually.

March 31, 06h

I remember coming across this technique once and I thought the person referred to it as the Shea Method. It survives the images off/css on scenerio and uses no plugin. While it does have an extra span tag, the tag doesn’t have to go around the text, just before it. The span tag gets a background image attached to it and when you apply a height and width of 100% to it, it basically just covers the real text. The real text never gets pushed out of the way and if the image doesn’t load you can still see what the header says.

Is this your method or someone elses (sorry I don’t keep up on all of the names for techniques) and is there a flaw to it? (besides the extra span tag that I know others will point out) I also know that nothing is 100% flaw proof.

I ask because I am planning on suggesting it for implimentation on our future redesigns. I would rather prefer just normal text, but branding guidelines may prevent that.

I know about the sIFR method and it seems promising, but I always prefer the simpler is better method.

Here is the code (i’ve replaced the <> characters with () to make sure it post correctly.)

h1 {
width: 500px;
height: 25px;
position: relative;
font-size: 12px;
color: #006;
#info {
background: url(isitbad.gif) no-repeat;
position: absolute;
width: 100%;
height: 100%

(h1 id=”info” title=”Is there anything wrong with this method?”)(span)(/span)Is there anything wrong with this method?(/h1)

Ric says:
March 31, 07h

I like the look of the gilder-levin technique, but I’ve spotted a problem with it.

If you resize the text in the browser it will - eventually - burst out from behind the image.

Obviously this matters more with some images on some sites but it might cause problems for limited vision users who have their browser render the text larger than the image.

March 31, 07h

Two days in a row Dave, I’m impressed. And both very good articles. I started learning about image replacement in “The Zen of CSS Design.” I was using something very close to the Rundle/Phark method for my previous site (although less successfull in cross browser rendering) so it’s good to see more discussion on it.

March 31, 08h

Thanks a ton nick :)
Stories (real one’s) that come from the blind themselves always make more of a convincing argument.

Tony says:
March 31, 10h

I know a lot of people really like the sIFR method, but here’s my major issue with it:

In an attempt to cut down on Flash based banner ads, all Flash content in my browser (Firefox) loads with a small round “F” icon. If I click it, it loads the Flash.

So, whenever I visit a site using sIFR, all the headings are just round “F” icons. I’d have to go through and click every single one of them…When I go to the next page in the site, I have to do it all again.

As Flash ads become more and more of a problem, attempts to block/circumvent them will also become more and more prevalent.

So, for me, I can’t stand the use of sIFR because it makes the site unusable for me.

March 31, 11h

How about using plain ‘ol JavaScript? We could even call it JIR…

Rene Enguehard says:
March 31, 12h

You could even call it JRE, Java Replaces Everything… Oh wait, that’s already taken…

Seriously though, you shouldn’t have to resort to JavaScript or Flash as stop-gap measures. There are proper uses of JavaScript (well, even that is arguable) and Flash. This is definitly not one of them.

I have a lot of trouble swallowing the fact that simple, correct, HTML with an attached CSS file for presentation, cannot fix this problem. With CSS3 we could but I’m fairly certain there are problems with that too. (There always have been in the past and I doubt the future is any different…)

In summary, I think you should pick whatever method fits your particular site. If your site has a lot of flash in it, why not use sFIR? You have nothing to lose since visitors need Flash enabled anyways to see your content.

I think it really depends on the particular site and how the technique integrates into the rest of it.

March 31, 12h

Dean, that one’s already be suggested (if I understand your suggestion correctly). Didn’t really take much of a hold since sIFR blows it out of the water…

March 31, 12h

Dustin asks ‘Is there even a population out there that uses screen readers that pay attention to the “look” of the page…’

I was discussing this with a blind friend a couple of nights ago. Like most people described as blind, he has a small amount of vision remaining. He uses Supernova, which incorporates both screen reading and high contrast display with zoom.

He told me that when dealing with tag soup or sites that insist on having long lists of links/navigation before the content, with no “skip” links, he will often give up listening and resort to the zoom option to try to track down the information he wants from a page.

So the answer is yes, even blind visitors will depend on the look of a page.

(FWIW, he views pages at a magnification of x32; try shrinking your browser window to 1/32 of its normal size to get an idea of his browsing experience…)

April 01, 01h

“I use the <h1><img /></h1> combo from time to time myself. It just has a weakness - flexibility. I can’t re-style a page from the CSS when an image is embedded. That’s what image replacement gets me that an embedded img doesn’t.”

However, the image in a header would most likely be content in this instance. Content goes in the markup, presentation goes in the stylesheet. While image replacement may be more flexible for some in terms of maintenance, the image’s “proper” place would probably be in the HTML code in this context.

Jim says:
April 01, 03h

> Sure you could do it the img alt text way, but that won’t give proper structure to the page like a header tag will.

Who said anything about not using header elements? Using header elements for headers goes without saying.

> It would be nice if you could just put header tags around the normal text image and use alt text, but that doesn’t cut it semantically or for accessibility.

In what way? Is the image a header? Yes. Is it accessible? Yes.

> For Accessibility purposes […] you want to make sure you use correct semantic markup and make sure to use it in places where it is supposed to be, like using header tags where there is a header in the document.

But an img element inside an h1 element *is* the correct semantic markup!

It seems to me that there’s a phobia surrounding img elements in the same way there’s a phobia surrounding table elements. Sure, many people abuse them, but when what you actually want *is* an image or table in your content, that’s what you should use.

April 01, 03h

Yup, during all the image replacement discussions, I’ve never seen anyone state exactly what’s wrong with this:

<h1><img src=”heading1.gif” alt=”Heading 1”></h1>

Works in all browsers that support images or alt, works with images turned off, works with CSS turned off.

You can also use PHP with the GD image library (or equivalents in other languages) to automatically generate them whenever a page is served, if you don’t mind the necessary coding, and processing overhead.

April 01, 04h

Well, if the reason you wish to use an image in a header is to make it look good, it’s presentation, not content.

April 01, 10h

“Yup, during all the image replacement discussions, I’ve never seen anyone state exactly what’s wrong with this:”

I totally agree and that’s the approach I use. Unless you need automated image generation this will be the most accessible and user-friendly approach in all instances, and there are even server-side methods you can use if you really need the automated generation of header images.

Dave S. says:
April 01, 11h

“Yup, during all the image replacement discussions, I’ve never seen anyone state exactly what’s wrong with this: <h1><img src=”heading1.gif” alt=”Heading 1”></h1>”

I don’t think there’s anything inherently wrong with it. Accessibility-wise, it’s pretty sound. You might lose some Google juice from the difference between in-page text and alt text, but the jury’s still out on image replacement’s results in Google anyway.

I use the <h1><img /></h1> combo from time to time myself. It just has a weakness - flexibility. I can’t re-style a page from the CSS when an image is embedded. That’s what image replacement gets me that an embedded img doesn’t.

There are countless reasons why moving the image to the CSS is good for flexbility — I can do things as broad as theme an entire site, to more subtle things like per-page colour variations of an image. You *can* do that with img elements and server-side code, of course, but this kind of presentational variation feels more suited to CSS.

Marc says:
April 02, 03h

I have been struggling with image replacement techniques myself, even to the point of writing an article about it. It may be utter nonsence (regarding webdesign I’m pretty much an amateur), and nowadays my worries about IE 4 probably seem overdone, but the article may still be useful to some, so here it is:

Unfortunately, the link to “Santa’s Image Replacement” doesn’t work anymore – I believe it was a little like the Phark method, except for a vertical text shift.

Today, I also found the following article: which deals with a method that seems to be related to: (to which I linked in my blog post).

These last two methods both use the z-index property in the CSS, an approach that doesn’t seem to have been mentioned in Dave Shea’s tally. So I thought I’d mention them here, as the CSS bag of tricks can never be full enough. :)

April 02, 07h

> Well, if the reason you wish to use an image in a header
> is to make it look good, it’s presentation, not content.

Exactly, this finally causes the need for replacement techniques. But there are more severe violations than using image elements in headlines, of course.

Nice article, by the way.

April 04, 02h

One thing that strikes me in particular regarding the Google issue (and I may just be going over something they’ve already proposed) is that perhaps they ought to alter the way their bot work so that it virtually renders the visited page, and can thus determine what is/isn’t visible. Stylesheets for web spiders, anyone?

yuccaplant says:
April 04, 07h

“But people find this scary, as you can select the text by dragging down on the element.” (Rob Mientjes - first comment)

As far as I can see (don’t have a mac) the scrolling problem occurs only in Firefox (so in Gecko-based browsers I suppose). I found out that setting ‘font-size: 0.000001em;’ resolves the scrolling problem (correct me if I’m wrong.).

Dustin Mellen says:
April 06, 04h

Well, I have another method I discovered after reading about this issue in the CSS Zen book. If you set the opacity of the text to 0% in the <span>, the text disappears from view but still exists in the web page. In theory, that would allow it to be read by screen reading software. The only pitfall to this method (I’m not sure if anyone else has tried this method, so I’ll assume I’m the first) is that if you disable image loading in your browser, the text will not appear even with the images gone. Let me know if this has been done and/or feasable. Here’s a sample of the I used:

#preamble h3 span {
display: block;
opacity: .0;
filter: alpha(opacity=0);
width: 300px;
height: 50px;

The second opacity setting is for IE as well as the width and height settings.

Dustin Mellen says:
April 06, 05h

I wish I could edit my last comment. I just had an idea. If you use the method I stated above and then, set the box that holds the image to return the text opacity to 100% when one hovers over it, you could see the text even though the image is not there. Not a perfect solution, but it solves the CSS on/Image off problem I stated in my previous comment. IE is still a problem. It doesn’t allow hover applied to anything other than a link.

Dave S. says:
April 09, 04h

One more regarding those who browse with images off/CSS on. I just received this email from an actual user:

Why dont you add some kind of alt-text so your navigation links at the top of the page are still accessible to a viewer with images disabled in their browser like me?

April 09, 06h

Wouldn’t it make all of our lives much easier if they made content: url(); work with the img tag? >: (

April 10, 10h

I have no idea if anyone still reads these comments, but I just came up with a new technique which is much better than all the pevious ones - it has no extra elemets and works in “CSS on, images off” scenario… all major browsers, including IE (even IE5/Mac). You can see it here: