Ever since Todd Fahrner made famous his Fahrner Image Replacement (Doug Bowman explains) technique, people that use screen reading devices have been complaining that it doesn't work as they had hoped.
Now, I do not have a screen reader, nor have I ever used one, but I believe that I have found a better image replacement technique that actually works for people with screen reading software.
The goal is to keep the text "visible" to the browser, but hidden to the user. That is to say, the text must not be able to be seen by the person viewing the website, but still has to be there.
What I have been doing is this:
<div id="replaceText">
Some text goes here...
</div>
With this kind of CSS attached to it:
#replaceText {
text-indent: -9000px;
background: url(bg.gif);
.... }
Now, what this does, is move the text 9000 pixels to the left (or "before", depending on in which direction your text is written), such that is it no longer viewable in the parent container.
The text is "still there", however you cannot see it. The background image shines through proudly, and the screen reader will happily read your extremely negatively-indented text, disregarding the background!
Update: Thanks to my friend "Vavoom"'s usage of his screen-reader, the above-mentioned technique is now verified to work with the JAWS screen-reading software.
Note: IE5 on Windows has a problem with the technique, where it negatively indents the text and background image. To fix this, place the image replaced div inside of an absolutely positioned parent element. Just experiment, there are other workarounds for this bug :)
THANK YOU!!!
I have been looking at the image replacement solution and finding it attractive, but entirely too problematic.
I found your suggestion and just tried it, viewing it both on the monitor, and with monitor off using JAWS, it works like a charm!
Fantastic. Thank you.
Posted by: vavroom | Tuesday, August 05, 2003 at 10:17 PM
very good indeed, i'll be trying this out and using it later on, thanks!
Posted by: p | Monday, August 11, 2003 at 02:09 PM
Uh-oh. This technique could kick your site off search engines. As well as you can throw in text meant for screen reader users, you could throw in some keywords or some other text fooling search engines. Hiding stuff like that the way you describe is used by SEOs (Search Engine Optimizers) since years with questionable results. I strongly suggest not to use it.
Posted by: Oliver | Monday, August 11, 2003 at 03:09 PM
I've done virtually the same thing by moving text below the threshhold with the line-height property. Good job!
Posted by: Jonathan | Monday, August 11, 2003 at 03:15 PM
Oliver:
That's definitely true. I should contact people at google or yahoo to see what they think.
Jon:
Kick ass website! That line-height idea sounds real useful, especially with very wide elements where the text-indent value would be really high, and a quick line-height value would be easier to write.
Posted by: Mike | Monday, August 11, 2003 at 03:21 PM
As a further tweak for use with headers, etc., how about:
<h1 style="background-image:url(header.gif);">
Header replaced with image
</h1>
<h1>Header without image</h1>
h1 {
background-image: none;
}
h1[style] {
background-repeat: no-repeat;
text-indent: -100em;
}
That way, if you want a h1 without replacing the text, simply use it as normal; if you want to use an image, stick it directly in the h1 tag, and the CSS selector for h1[style] will apply the text-indent to only h1 tags with style attributes.
Posted by: Andy | Tuesday, August 12, 2003 at 08:55 AM
That's pretty slick Andy, I'll have to try that!
Posted by: Mike | Tuesday, August 12, 2003 at 11:24 AM
This technique is not accessible for me. I mostly surf with images disabled and sites that use FIR are sometimes really plain:
http://levin.grundeis.net/files/20030812/images_off.jpg
However, there is a solution:
http://levin.grundeis.net/files/20030809/alternatefir.html
(which sadly relies on an additional span)
Posted by: Levin | Tuesday, August 12, 2003 at 07:24 PM
p.s. You were mentioned on Zeldman.com
Posted by: Paul Watson | Wednesday, August 13, 2003 at 05:40 AM
Rob, can you post some code?
Paul, I know!!! I seriously thought I was going into cardiac arrest when I saw it. I met Jeffrey just this past year in Albany, NY, and had him sign my PowerBook!
Levin:
Its tough not using a span tag AND have the technique work when images are turned off (CSS on). I think everyone and their brother is trying to find that holy grail, and when they do, you can bet that it'll be all over the net within minutes :)
Posted by: Mike | Wednesday, August 13, 2003 at 10:36 AM
Cool technique, IE does have some trouble rendering unordered lists (and a bunch of other "regular" HTML tags lol), so before I make a decision, I always check my page out in Lynx to see if the layout sans-CSS works or not.
Posted by: Mike | Wednesday, August 13, 2003 at 02:07 PM
In reference to the posible search engine problems, I think its important to note that most search engines ignore CSS.
In fact that is one reason to switch to CSS based design - your code is more content based and hence easier to search and index.
Thats one thing that A List Apart and others have pushed about it..
Search engines tend to analyse content for spam, rather than a technique. Hence loads of keywords is flagged, but not a short description.
Again, as most search bots ignore CSS there should be no problem with this technique in modern search engines.
Posted by: Greg | Friday, August 15, 2003 at 09:50 AM
I remember reading that ALA article, and I believe you're right.
Posted by: Mike | Saturday, August 16, 2003 at 07:57 PM
Your technique with the text-indent fails in IE5.5, at least for me. I have a DIV containing an H1 and a P, with the background image set. The DIV height and width dimensions are the same as the background image, and I used your text-indent: -100ems to move the text out of the way. Unfortunately, in IE5, I get a blank space where the DIV should be. I'm still tweaking it - if I come up with a solution, I'll post it here.
Posted by: Bob | Tuesday, August 19, 2003 at 09:44 AM
Bob:
Thanks for checking in IE 5.5, I think that's one of the few browsers I have left to use this technique with.
Can you post a screenshot (or a link to a screenshot lol)? I'd like to see what it looks like and if anything could be done.
Mike
Posted by: Mike | Wednesday, August 20, 2003 at 10:54 PM
Remember that IE.5.5 has a broken box model and so you will need to use the workaround.
Incidently I use a variation on the above for headings. I use:
#replaceText h1 {
text-indent: -100em;
overflow: hidden;
background: url(bg.gif);
line-height: size of bg.gif;
}
Works on IE5.5, IE 6.0, NS 6.2 , NS 7, Safari 1.0.
Sadly it breaks on IE5.2 on the Mac, but as Safari and Mozilla are both available on the Mac I'm not too concerned about this.
Posted by: Aled | Monday, August 25, 2003 at 09:10 PM
Aled:
I really like the combination of using the line-height and the negatively indented text.
I'm going to be incorporating both from now on ;)
Also, I was asked to write an article for Made for All regarding accessible image replacement techniques, and I think that I'll mention the line-height idea as well as the text-indent one as ideas to conquer image replacement.
I'll post back here when its all said and done with to see what everybody thinks.
Mike
Posted by: Mike | Tuesday, August 26, 2003 at 12:19 AM
Recognition from Zeldman, Congrats...great tip...
Paul
Posted by: Paul | Wednesday, September 10, 2003 at 12:56 PM
Sorry for the delay in the screen cap. I hadn't been back here since I posted my comment above. However, Aled's reminder about the box model in IE5 (something I almost never remember) should fix the problem.
Posted by: Bob | Tuesday, September 23, 2003 at 03:19 PM
Of all of the FIR image replacements I've seen, I believe this is the best one. You can also make them be links!
CSS:
h1 { background: your_bg_info; height: 30px; text-indent: -100em; overflow: hidden }
a { display: block; height: 30px }
<h1><a href="/">Home Page</a></h1>
Tested Opera 5/6/7 and NS 6/7 (NS 7 wasn't actually displaying the bg image, but then again, it only displays some of the images some of the time for me. Link still worked, though).
Posted by: chris | Friday, October 24, 2003 at 12:05 PM
Great call! Some people take the method at face-value, and forget that you can pretty much do whatever you want with the code to make it fit your design.
Consider if you are replacing a logo on the right side of your page... instead of doing a negative text-indent, just take the negative sign off and push your text off to the right. Or increase the value to something like -10,000 lol.
Oh, and I realized that there's really no need to keep the overflow rule in there, if you're moving the text a virtual "foot" off the screen anyway, there's no chance your user will ever see it. Overflow is what chokes IE5 for the Mac and some other browsers, so see if that helps.
Mike
Posted by: Mike | Friday, October 24, 2003 at 01:46 PM
The text-indent technique doesn't work in IE5.01 unless position: absolute; and overflow: hidden; are added. this breaks it in 5.5 though.
Posted by: Seth Thomas Rasmussen | Tuesday, March 23, 2004 at 12:16 PM
After having worked with the -text-indent method, FIR, and LIR as image replacement methods, I have found that applying the negative Text Indent is a successful method for replacing text with an image on most browsers. Like all workarounds, there is no concrete solution, and the largest drawback currently with this method is that with images turned off, the stylistic information is lost (the "alt text" if you will). However, despite this shortcoming, this method of image replacement requires not only the smallest amount of changes to existing CSS, but is the most compatible with preexisting layouts and designs.
Thank you very much for this wonderful article.
Posted by: Jakob | Wednesday, April 07, 2004 at 06:08 PM
For the record: The negative text-indent method will work in IE/Win 5.01, *if* absolute positioning or floating are used on the containing element. Otherwise, IE5.01 will correctly outdent the text, but will carry the background-image with it - even if the background image is aligned right instead of left.
An alternative solution is to use an internal span and apply the text indent to that, and the background-image to the container element. However, this defeats one of the main advantages of this technique.
Posted by: Alun David Bestor | Monday, May 10, 2004 at 03:41 AM
Great pickup Alun, thanks!
Posted by: Mike | Monday, May 10, 2004 at 02:07 PM