Mobile version (Display Regular Site)

Skip to: Navigation | Content | Sidebar | Footer

Weblog Entry

Accessible Image Replacement

December 12, 2003

Image replacement is back in the news — Levin Alexanders’ ‘Graphical Headings’ is going around again. (note that Tom Gilder also brought it to our attention around the same time)

Classic FIR has three problems, which I summarized this summer:

  1. Screenreaders don’t read content hidden with display: none;
  2. A superfluous <span> element is introduced
  3. People browsing with CSS on, but images turned off don’t see anything.

Levin’s method solves two of these problems, namely 1 and 3, but introduces a new one: transparent GIFs are unusable, due to text beneath showing through the transparent gaps. There are a few ways around this, by setting text colour and size to be all but invisible, but it’s still a problem. The code is also far more complicated than it should be.

Gilder/Levin Method
	<span></span>Image Replacement

/* css */
h2 {
	width: 329px;
	height: 25px;
	position: relative;
h2 span {
	background: url(sample.gif) no-repeat;
	position: absolute;
	width: 100%;
	height: 100%;

Alternatively, there are two other techniques available now that solve problems 1 and 2 but leave 3 dangling. Specifically, Phark Revised (due to a Safari bug) and Radu Darvas’ new variation announced in a Web-Graphics post. Both use relatively simple code, and test well across browsers:

	Image Replacement

/* css */
#header {
	text-indent: -5000px;
	background: url(sample.gif) no-repeat;
	height: 25px;
	Revised Image Replacement

/* css */
#header {
	background: url(sample.gif) no-repeat top right;
	width: 2329px;
	height: 25px;
	margin: 0 0 0 -2000px;

So here’s where we’re at. We haven’t managed to knock off all three problems with one unifying method yet. There’s a choice, and which pill you choose says a lot about your priorities.

You take the red pill, and you contend with a tangle of code, but you guarantee equal access to everyone. You take the blue pill, and your code remains simple and elegant, but you cut off a tiny percentage of your users who might just, might just be surfing with CSS enabled but no images. It’s said to happen more commonly in European countries where dial-up access is metered, but that’s all we have for statistics.

Either way, we all know by now that using display: none; is out. We haven’t got this problem totally licked yet, but we’re two thirds of the way there. Not bad for a technique that has been in the public eye for only 9 months now.

Reader Comments

Lenny says:
December 12, 02h

Ideally, an :images pseudo-element would be added to CSS, so you can use code such as:

h2#replace {
color: #abc;

h2#replace:images {
background: url(heading.png) no-repeat;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;

Dave S. says:
December 12, 02h

:content will do that.

But CSS3 isn’t even close to being finished. In maybe 10 years once it’s done, implemented, and running on a critical mass of browsers, this will be the ultimate replacement.

matte says:
December 12, 02h

One aspect of the new techniques that will need some working on is combining them with the rollover-no-waiting technique.

The problem that I encountered after spending all of about 5 minutes trying this is the issue with “background-position’ for the hover state of a link using the Radu and Pixy techniques.

I am using the Pixy technique on a redesign of a site I’m working on. I’ll see if I can figure something out.


matte says:
December 12, 03h

Discovered something else that caused a problem for me with the Radu technique. Links that are lined up to the left of the header weren’t clickable. I have a nav box floated to the left of my right side content and the links directly inline with the headers weren’t clickable. I had set the header to a width of 2000+ the width of the image and the margin-left to -2000px. Links below the horizontal line of the headers were clickable.


December 12, 03h

I just posted about something similar to this involving LIR (which is my image replacement technique of choice so far).

LIR does solve issues 1 and 2, but not 3. One question that I always seem to find myself asking about issue #3 is: How common is it that someone will surf the net with CSS enabled and images disabled? In my seven years of using the net, dealing with the net, dealing with people who are dealing with the net, I’ve only met one single person who has ever said that he regularly surfs the net with images turned off. And he was a crazy old man who wouldn’t part with his Windows 95 box running a 28.8 modem… and this was in 2001.

Now, I understand that accessibility is an important concern, and that the semantic web should make sense. But aren’t there more people using Netscape 4.x than there are people surfing the web with no images? In a world where 56k (and upwards) internet speeds are the norm, if not the bottom end, don’t you think it’s time to stop supporting this outdated technology of slow modems and slow computers? We all dropped Netscape 4.x like a bad habit as soon as we could. Many people are talking about dropping IE5/Win as soon as we can. Why are we still pandering to users who manually disable images in their web browsers?

Now this isn’t meant as a put-down to anyone, but as I said earlier, I ask myself this question everytime I read about issue #3 involved in image replacement techniques. And I’m just wondering why?

On a separate note, using text-indent to move text out of the way also moves the background image out of the way as well in IE 5.0 for Windows. IE 5.5 seems to be alright, though. Just thought I’d point it out…

Eric says:
December 12, 03h

Why is #3 even a concern? There is already a solution for it called alt text. There is another solution, which would be having your site not send CSS to people that don’t accept images, but I know that is an evil server side technique. Either way I think its such a rare case, its like saying the whole stadium sucks because there are a few seats with bad views.

(also, why do I have to fill out this form every time, despite always clicking remember me and having all cookies accepted? IE6/WinXP)

Levin says:
December 12, 04h

Eric: Why is #3 even a concern? There is already a solution for it called alt text.

Images replaced with CSS don’t have alt-text (you could use a title-attribute and change the bg-color to indicate that there is something missing)

Ryan: Why are we still pandering to users who manually disable images in their web browsers?

Why not? Why should we give them an unusable page?
And it _is_ a problem:

Eric: There is another solution, which would be having your site not send CSS to people that don?t accept images

This can not be done server-side. You can do it via Java Script:
Or provide an alternate Stylesheet

ste says:
December 12, 04h

Personally, I’m using the Leahy/Langridge method. I think it’s less “hacky” to use the box model hack to support IE5/Win than to add an extra span that serves no purpose. Also, though it’s not a perfect solution to the #3 problem, using a title in that situation is still a fairly acceptable solution. That said, I can’t wait for a better technique to come along that meets all three criteria.

Unlike the last two comments, I don’t think people who surf with images off should be ignored or punished simply because they choose to surf that way. The difference between these people and those that use Netscape 4.x/IE 5 is that these people are making a conscious decision and likely have a very good reason (sure, bandwidth is available but not always cheaply!) whereas those generally still using Netscape 4.x/IE 5 are doing so out of ignorance or obstinence rather than from an intelligent choice. I guess I just don’t see the point in “punishing” someone for deliberately making a choice like that.

Levin says:
December 12, 04h

Btw, is there anyone who has combined Phark/Radu with CSS3s content-property?

That would be the ultimate solution:
- an image in all popular browsers
- a _printable_ image in all CSS3 browsers (Opera and, probaby, the next release of Safari)
- alt-text in all CSS3 browsers if images are disabled.
- no additional markup needed.

I’d love to see a working example.

Lach says:
December 12, 07h

Ryan, #3 will become a bigger problem as more third world countries become more hooked up to the net. Shaky lines / slow connections means that they’ll quite often have to turn images off, especially with the trend in some areas of web design towards assuming that people have high speed connections. And as there are a lot more people who have yet to access the net, than already do (600 M right now, IIRC), the problem will be an increasing one, I’d imagine.

Michael says:
December 13, 01h

If adding a couple of tags is going to mean that some users aren’t caused any confusion, then it’s kinder to do so. But I have a feeling that if someone in the U.S. or Canada did use the second method, he’d be more likely to get a note from a fellow author saying:

“I notice you’re using Phark, John. But I like to browse …”

than he would be to get email from the Vacluse or County Cork or Dorset saying:

“Dear Mr Smith, I enjoyed your site, but I wondered why you hadn’t used any headings.”

If the first guy was on Windows, then he would obviously be using IE, because you can toggle CSS on and off in Mozilla or Opera very easily. The first guy would also know that just as writers like Flaubert and Kipling felt compelled to revise and pare down their prose, so some HTML authors seem to feel a similiar pull. So he would be asking for a lot.

It’s just my feeling that that would be the more likely scenario. But if it’s at all likely that the second type of guy exists, then it’s good help him.

Maybe this is a pointless post of mine, because it doesn’t address the coding problem.

Adrian says:
December 13, 01h

Back in ‘98 I often browsed with images off because my ISP capped bandwidth at 120MB p/month!
I was using IE4 at the time so I would have fitted the ‘Images off, CSS’ on profile. Let me tell you that it made the web very hard to use because not many sites used ALT text correctly, if at all, but at least IE would draw an outline of where an image would be so you could get an idea of the site’s intended layout. Also, for ALTless image links, I would have to guess the destination based on the url that comes up in the status bar.

As I’m not a fan of meaningless spans, my suggestion would be to sniff for disabled images with javascript as per comment 7 and switch to an alternate stylesheet if this is the case. Also provide an alternate stylesheet link for non-javascript users. This would have satisfied me when I browsed that way.

Nicolas says:
December 13, 01h

#3 (CSS on / images off) happens to emails than contain HTML, when the email reader is Thunderbird (Mozilla too? others?) and the option “block loading of remote images in mail messages” is checked.
FYI this very nice option prevents a spamming technique that confirms your email address by sending a custom “image” request to the spammer’s server.

This is probably a small audience so far, but it will surely grow.

Moose says:
December 13, 01h


Problem solved: (for any CSS2.1 browser):

Submitted this right now to CSS-D. Enjoy!

M. (not a graphic artist)

Moose says:
December 13, 02h

A follow-up:

CSS3 may be far off, but CSS2.1 is just around the corner! This technique may be combined with the CSS3 method, as the latter takes precedence, and also with the “multiple backgrounds for one element” technique.


Michael says:
December 13, 03h

#12 “not many sites used ALT text correctly”

Yes, that’s bad, isn’t it?

Here in the UK, telephone connections legally had only to be good enough for voice not data. That has now changed:,39020645,2138055,00.htm

Theoretically, bandwidth should not now be a problem for any UK user - specially if authors consider page-weight. Practically speaking, I’m not sure that the UK PSTN is up to the data transfer rate set by Oftel.

My preference is to make things easy for users, so I think I would use the spans. But I did think that there were some further hidden assumptions there that it might be worth making explicit.

My thought is that for the Phark IR method to cause me problems, I need to know enough about my computer’s settings to switch images off, but not enough to know that it might be worth checking how a page looks without CSS.

Plenty of users won’t know about IR methods, but certainly some will have discovered that toggling off CSS sometimes helps them to read a page. For example, sometimes stuff you know must be there (and that would probably show up on a CRT but not a TFT screen) doesn’t show up because of low contrast.

MSIE doesn’t allow me to go in-and-out of CSS easily. That’s not a fault to be sure, but it’s certainly a lack of functionality in that browser.

At any rate, Opera deserves a plaudit for putting a icon that lets users do that kind of thing in a prominent position at the top left of the screen. And, I guess, another because Moose’s method apparently works in it.

December 14, 01h

I’m glad some people find the negative text-indent trick to be helpful ;)

I can’t wait until we can use the content property to fill-in/add-on information to our page. Unfortunately, “that browser we all know that has an 80%+ market segment” will not support CSS3 until at least 2005/6 when Longhorn comes out. Am I holding my breath for full CSS3 implementation? Yeah right.

csant says:
December 14, 06h

Re: Moose :: Problem solved: (for any CSS 2.1 browser)

positioning of generated content is still an issue. your sample looks problematic in firebird on a small screen… h1 badly overlapping p.

greetings to the northpole…

Moose says:
December 14, 08h

The fact that H1 overlaps P for screens smaller than my palm has nothing to do with image replacement, but everything to do with fixed positioning of P and the palm size.



December 15, 06h

Is this REALY a job for CSS? Especially with the problems already mentioned?

What’s so wrong with using:

<h1><img src=’my_heading.png’ alt=’My Heading’></h1>

Text readers (or browsers with images switched off) usually display the alt tag.

December 15, 06h

Appoligies Eric, I must have got HTML word blindness and skipped your comments :-/

Eric says:
December 15, 07h

I apologize for a silly comment, I don’t know what I was thinking since the solution is supposed to have text in text and not use images unless CSS and images are on.

As far as detecting if images are off, can’t you just check the Accept header to see if they are accepting images? I don’t know if this is reliable enough to work.

Niket says:
December 15, 08h

I agree with Richard. I see no reason why one shouldn’t use

The only reason I was provided at one of the message boards was “because PDAs don’t support 700px wide images”.

So the main question that you haven’t yet answered is:
How EXACTLY is FIR more accessible than ?

Dris says:
December 15, 09h

Richard and Nicket: I came to the same conclusion at one point, but then I thought, “Wait! What if I want to use the same markup but switch out the CSS file for an alternate design?”

Therein lies the problem. The IMG tag should only be used for content-related images, stuff that won’t change with a redesign, such as graphs and photographs. Decorative, style-related images should be in the CSS. Separation of design and content.

Niket says:
December 15, 10h

Dris, now wouldn’t that be using one technology (CSS) to hide the shortcomings of the other (XHTML).
The shortcoming being that “Shelley Allegro” font (quoted from the StopDesign FIR article) may not be available to the user, needing you to use a background image instead.

If thats the case, doesn’t the image become the content itself? FIR is “REPLACEMENT”, so it has to do with CONTENT not STYLE. So, wouldn’t a JIR (javascript image replacement) be more appropriate here?

I agree that FIR is a good tool. We should treat is just as that - A tool. FIR is a wrench, we are spending way too much time thinking about the wrench, when our nuts and bolts themselves are not optimally designed.

I guess I am just thinking aloud here.
And yes, although I say this, I still use FIR on my own website.

Levin says:
December 16, 02h

Hey, this is great! *applause*

It works in Opera 7.23 and Firebird.
And the markup is clean enough for me.


Levin says:
December 16, 02h

Does not work in Konqueror 3.1.3 (Text is in front of the image)

Andrew says:
December 16, 04h

<h2><span>Image Replacement</span></h2>

/* CSS (sorry, not tested on every browser yet [works on IE/Win and Mozilla]) */

h2 {
background: url(image.gif) no-repeat;
width: 200;
height: 80;

h2 span {
position: relative;
z-index: -1;

Works with existing FIR markup
Text visible if image doesn’t load
Fairly clean CSS

Still needs <span> tags
Won’t work with transparent images

Andrew says:
December 17, 07h

I’ve been trying to solve the problem by “faking” generated content with list-style. Unfortunately, it doesn’t work in IE (which defeats the purpose of doing it, since other browsers support “real” generated content). Here’s the code anyway, in case someone can get something similar working:

h2 {
display: list-item;
list-style: url(image.gif) none inside;
overflow: hidden;
width: 200; height: 80;

Moose says:
December 17, 09h

I’m sorry for breaking the URI I posted before. Cool URIs don’t change… Things tend to happen though, and facing a difficult choice, I made an equally difficult decision. So here is the description, which contains the link to the experiment:

mea culpa,


p.s. Herr Levin updated his superb grid:

tony melvin says:
December 19, 01h

I am a Canadian living and working in Germany. I am a screen designer/content manager. I have never seen any German surfing with the graphics options switched off. I have travelled abroad and have never witnessed this. The Germans view the design elements as an important factor.

The Canadian I know- they are bad for this. I could never understand this.

Pei Yi says:
December 23, 08h

Andrew, it seems a good idea. To make it work, replace overflow by text-indent: -99px, depending
on the width of the text, not the image.

thus you have:

h1 {
display: list-item;
list-style: url(image.gif) none inside;
text-indent: -200px;
width: 200; height: 80;

This works in IE6, but not in Opera 6. If this works it should solve all 3 of the major problems. Unfortunately, when I turned images off in Opera and IE, the image still loads. Apparently, these browsers do not recognise list-item images as images.

Lastly, as a user of Opera, I find it handy to turn off images when the download is slow. All it requires is a simple press of the ‘g’ key. Thus there are occasions when I browse with images off.

Pei Yi says:
December 23, 09h

sorry, the width of the image will do as well.

Tim Bannister says:
December 31, 07h

I don’t think this is a job for alt=”…” particularly, or for CSS. I’d have thought that would be more appropriate, from a standardisation viewpoint.

January 04, 08h

Well, it still seems like there is no solution. Which method should we use for now? Here is my opinion:

January 05, 07h

Here’s a new method I thought of (based on Gilder/Levin). I call it the “double-span” method:

Revised Image Replacement

/* css */
#header {
width: 329px;
height: 25px;
position: relative;
#header span {
width: 100%;
height: 100%;
position: absolute;
background: url(page-background.gif) repeat;
#header span span {
background: url(sample-opaque.gif) no-repeat;
width: 100%;
height: 100%;

The background should match the page background. This could be a 1px solid color image, or a pattern that has been offset to match the bakground. That will get rid of the transparency problem, but does add another span element :(.

January 09, 07h

I hit a snag testing the Radu method in Safari. It does not play well with floats. That is, even with a margin-left of -10000000 pixels the h1 text will still end up along the right edge of a left floated element. For example I have a 200px wide navigation menu floated left with the content on the right. In Safari the text is not pushed off the left side of the screen but rather is 200px from the edge of the window.

Phark also has a problem with ie 5 in that the negative text indent is applied not only to the text but also to the background image, in effect making it invisible and completely inaccessible.

Martin says:
February 21, 04h

One could use media=”screen” or @media screen {} or @import “screen.css” screen for an image replacement using display:none, screenreaders should ignore it …

MikeyC says:
February 21, 05h

“One could use media=â€�screenâ€� or @media screen {} or @import “screen.cssâ€� screen for an image replacement using display:none, screenreaders should ignore it …”

Screenreaders work by reading right off the screen, so they wouldn’t ignore the rule.

August 03, 12h

I couldn’t find any references to this method after some (quick) searching, but I’m sure it can’t be original:

;font-size: 0
;text-indent: -9999px
;width: 300px
;height: 100px
;background-image: url(“image.png”)

The arbitrarily large negative text-indent moves the text several metres off the left edge of the screen. Simply indenting the text leaves an underline in Mozilla if the text is a link; the zero font-size hides the text in Mozilla (it merely reduces it in IE6 and Opera).

I’ve only tested this in IE6, Mozilla and Opera 7.5; according to a post above, the background image won’t be shown in IE5; the method may well also fail in KHTML. Frankly, IE users are lucky they’re seeing any style at all.

Benefits: no extraneous XHTML required; display:none isn’t used so screenreaders should be fairly happy; pretty lightweight CSS.
Drawbacks: blankness with images off, css on; allegedly fails in IE5.

Ross says:
October 25, 09h

In summary, which do we think is the best method?

I personally have an issue with any negative text-indent option as this may cause issues with a manual edit at google. Moving text off the screen could be seen as an alternative to white text on a white background hidden text.

I want to make the code as clean and as accessible as possible but cannot risk the threat of a google ban in doing so.