Choose an accessible image replacement method

The technique of using CSS to replace normal HTML text, mostly for headings, with a background image in order to achieve a particular look has been talked about many, many times since early 2003.

Several different image replacement methods have been proposed, each with their pros and cons. Some methods create accessibility problems, while others place restrictions on the type of image you can use or force you to use extraneous markup. No method that I am aware of is perfect.

What surprises me a little is that I still see people using image-based techniques that do not work at all for people browsing with images off. One of the tests I perform when checking sites for accessibility and universality is to simply turn off images in my web browser. In some cases that makes text disappear because an image replacement has been used that does not account for people with CSS on and images off.

In most cases you can and should use an image replacement method that avoids that problem. On the few occasions when I need image replacement I turn to either the Gilder/Levin Method as described by Dave Shea or, if the replaced text is linked and CSS support for IE/Mac is required, the Gilder Levin Ryznar Jacoubsen IR method.

A drawback that both methods share is that they require adding an empty inline element to the markup, but that’s a small price to pay for making the text available to everybody. Another drawback they have in common is that they don’t work well with partially transparent images, so if you have to use transparency you’ll need to decide whether to adjust the design or hide the replaced text from people with images off.

In the end it’s your call, but I hope this has at least made you aware of one problem image replacement can cause as well as a couple of methods that eliminate it.

Posted on December 3, 2007 in CSS

Comments

  1. I never realized that this caused an accessibility issue. I need to rethink some of the things that I have been doing to ensure that I’m not making my sites inaccessible in this manner.

    Great post, good information to think about.

  2. On my sites I use a variant of the Phark Revisited method. I have tested this with most browsers and I think it’s the best way for my personal claim.

    If I use MS IE 4/Webby Mobile on WindowsCE or Blazer 4 on PalmOS 5 the text from “CSS: text-indent: -5000px;” is displayed over the background-image on PDAs. Mozilla Minimo and Opera Mobile work fine with the method.

    If I disable all CSS or use Lynx, OffByOne or a Screen Reader, so I don’t need CSS and the h1-text is at the right position.

    Currenty most commonly browsers have no problems, also Opera Mini on Mobile Phone work correct.

  3. December 3, 2007 by Justin

    Given that CSS image replacement techniques are usually used to replace a specific heading with a specific image, is there any accessibility benefit over a simple

    <h1><img src="/path/to/image.png" alt="Header Text"></h1>
    

    …?

  4. I use Gilder/Levin (I think that’s the one I use). I needs an empty span, but it is an accessible method, even with images off.

    I do know of yet another technique that might be worth noting. It is accessible, and does use extra markup in the form of a span (albeit not an empty one). It’s called the BIR Method was created by a friend of mine, Neil Venditto.

  5. Does visibility:hidden; affect screen readers the same way display:none; does?

    There needs to be a way to tell the screen readers which text to read and which text to mute.

  6. Well, I totally agree with Justin’s solution. There isn’t any advantage for anyone to make those image replacement… Before the “content” propriety will be largely supported, I think the most interesting solution would to use “:before” pseudo-element like this:

    h1:before {display:block; content:url('logo.png');}

    h1 {overflow:hidden; height:100px;}

    Everything will be ok even if CSS’on & images are disabled… but stupid IE doesn’t understand it. Hopefully, this solution seems to work pretty well:

    :before and :after in IE7 and below

  7. I came up with my method over a year ago, it works in Firefox, Opera and Safari in an accessible manner, without any extra markup, goes on to use the Leahy/Langridge method in IE and degrades gracefully in any other browser.

    I just can’t wait for :before to be supported fully!

  8. Funny you should mention this, as I’ve recently come across something I found over at Alsacreations, a CSS and (X)HTML tutorial site.

    As I was converting my 4.01 transitional to strict, I thought it might be an idea to get rid of my javascript image rollover, and replace it with one of my adapted hoverlist (Nathan Smith’s hoverbox) methods.

    Eventually though, I adapted Alsacreations’s image replacement technique only after failing to get my own flavour of a rather dodgy definition list to validate in a strict doctype.

    I’ve now incorporated it into my (hardly ever updated) 4.01 strict home page.

  9. then again, sometimes you have to be pragmatic and choose a method that does not work for images off / css on - which, as a personal view, i treat as an edge case of universal access, not accessibility for user with disabilities. it all depends on the situation though.

  10. December 4, 2007 by Jonathan

    For the past few years, I’ve been using the BIR Method (mentioned in comment 4). It uses the z-index property, and all my tests have shown it to be very accessible.

  11. Well, I totally agree with Justin’s solution.

    Why? There’s nothing wrong with it. Having said that, when I do use IR, I use the Gilder Levin Ryznar Jacoubsen method.

  12. December 4, 2007 by M Koher

    sIFR anyone?

  13. December 4, 2007 by Roger Johansson (Author comment)

    Justin:

    Given that CSS image replacement techniques are usually used to replace a specific heading with a specific image, is there any accessibility benefit

    Well, the text is there for real in the markup if you use image replacement, which means it will be handled just as a normal heading. A screen reader wouldn’t need to announce that there is an image, for instance.

    patrick:

    then again, sometimes you have to be pragmatic and choose a method that does not work for images off / css on - which, as a personal view, i treat as an edge case of universal access, not accessibility for user with disabilities.

    Yes, you don’t always have enough control over the markup to use an image replacement method that works for everybody.

    I agree that images off/CSS on is not really about accessibility for people with disabilities, but I wouldn’t call it an edge case. I have no statistics on how many turn images off, but there are many millions of people who access the Internet via dialup modems. I know that when I did that I used to turn off images to speed things up.

    As you say it depends on the situation.

  14. Like M Koher says… What about sIFR

    What is your opinion on using that approach to create graphic headlines?

  15. I don’t use images and logos that often i headers, but I had a case some time ago where I had to, and used the following CSS:

    header h1 {

    background: #fff url(‘gfx/logo.jpg’) no-repeat; width:338px; height:90px; text-indent:-9999px; }

    This solution didn’t require any extra markup.

  16. I also use Kristin’s method and have never had any problems with it.

  17. @Kristin: Try disabling images and reload your page, and you’ll see why this isn’t a good method.

    It may work with screen readers, but for dial-up users like me (CSS on, images off) the result will be no image and no text.

    I know that the likes of patrick don’t think that people like me have any right to access websites. They apparently expect me to sell my house, euthanise my cats and give up my quiet life in the countryside for expensive city living so that I can get broadband. I suppose I could always poke my eyes out; that seems to be an acceptable reason to these guys.

  18. @Tommy: Now I feel almost ashamed that I didn’t test my method with css on but images off. It was actually all I found after two days searching for a css method for this, but hopefully this post will lead me to better ways. I think I’ll try out the BIR method that was posted here instead, it looks much better, even if you have span, it’s not empty.

  19. December 4, 2007 by Stevie D

    Given that CSS image replacement techniques are usually used to replace a specific heading with a specific image, is there any accessibility benefit over a simple [h1][img src=”/path/to/image.png” alt=”Header Text”][/h1]

    I’m not sure to what extend browsers and accessibility software recognise that “Header text” is part of [h1] - I know that IE6 fails to render alt text as anything other than plain ordinary body text.

    sIFR anyone?

    Fine if all you want to do is to have the heading in a particular font, but if you want to turn it into a logo or artwork, sIFR won’t help.

  20. I know that IE6 fails to render alt text as anything other than plain ordinary body text.

    That’s not true.

  21. It seems to me that the closest thing we have to a perfect solution would be the img tag, and I’ve been serving them up dynamically for nearly two years. However, the accessibility community’s reaction has been a collective yawn. Yeah, I feel a bit neglected.

  22. December 4, 2007 by Stevie D

    @Lance:

    That’s not true. It’s what happens on both my home and work PC. If I insert an [img] tag with a dummy filename into an [h1] and a [p] tag, the alt text is rendered in exactly the same way on both occasions, there is no way to determine visually that one line of text is a key heading and one is just ordinary body text.

    I know that Opera does enlarge and embolden alt text that is contained within an [h…] tag, and I think Firefox does as well, but I’m not sure. IE6 certainly does not.

  23. December 4, 2007 by Stevie D

    One thing that I’ve not seen mentioned is that, if you are using an image replacement technique of any sort, if you have used even a slightly arty design, it may not be legible to users with poor vision.

    For that reason, it may be worth repeating the textual content of the heading in a title attribute, so that it will appear as a tooltip in an ordinary font that everyone should be able to read easily.

  24. December 4, 2007 by Linus Boström

    Without touching the importance of accessibility: How long are we going to take into consideration IE for Mac, since it hasn’t been available for OSX?

  25. December 4, 2007 by Sascha

    Most of the time I’ve been using the Phark IR-Method (guilty for not taking the CSS on/Images off Problem too serious). Now my favorite Method is the Gilder Levin Ryznar Jacoubsen IR.

    I’ve never heard about the BIR Method, which looks very clever. Are there any known issues with this Method?

  26. December 4, 2007 by Roger Johansson (Author comment)

    sIFR can be an option if all you need is a specific typeface. I have only used it in a couple of projects. I find it a bit clunky, it slows down pages (or at least makes it feel that way, which is the same thing), and because I am spoiled by the way Mac OS X renders text I think it’s not good looking enough to justify its use.

    The best image replacement is no image replacement ;-).

    Carl:

    It seems to me that the closest thing we have to a perfect solution would be the img tag

    It could be a very good option, but it has problems. Like Stevie D says, it doesn’t seem possible to control the size of alt text in IE 6. It’s also likely that it does not have the same SEO benefit as real text.

    Linus:

    How long are we going to take into consideration IE for Mac, since it hasn’t been available for OSX?

    It depends on what you mean by taking it into consideration. For the last couple of years I’ve hidden CSS from IE/Mac (unless full support for it is specifically requested by the client), and it doesn’t get any JavaScript functionality either. That said, the poor few who are still using IE/Mac should at least get a legible page that lets them get at the information.

    IE 5.2 was available for Mac OS X by the way.

  27. Considering the implications of replacing a header with an image, is it not a case of the wrong tool for the job? Does brand building and/or design have to be detrimental to the content and impair accessibility?

    Not being a designer I’m probably not in the best position to justify the use of a styled header but I just don’t get this futile IR ‘problem’.

  28. First this:

    Several different image replacement methods have been proposed, each with their pros and cons. Some methods create accessibility problems, while others place restrictions on the type of image you can use or force you to use extraneous markup.

    Then this:

    … it doesn’t seem possible to control the size of alt text in IE 6. It’s also likely that it does not have the same SEO benefit as real text.

    SEO indeed. Alt text can be enlarged but not styled in IE6. I stand my by original statement: closest thing we have now to a perfect solution. Your yawn is duly noted.

  29. I read Richard Rutter’s related post where Shaun Inman said one could use JavaScript to enable/ disable image replacement on the spot — since his quick proof of concept is no longer available online, here is a code snippet that might fit the bill:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
              "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Javascript-enabled Image Replacement</title>
        <style type="text/css" title="text/css" media="screen,projection">
        /* <![CDATA[ */
        .img #foo {
            text-indent: -9999em;
            background: url(http://www.456bereastreet.com/i/about-head.gif) no-repeat;
            width: 35px;
            height: 47px;
        }
    
        /* ]]> */
        </style>
        <script type="text/javascript">
        // <![CDATA[
        (function(token) {
            var img    = new Image;
            img.src    = 'http://www.456bereastreet.com/i/about-head.gif';
            img.onload = function() {
                if (arguments.callee.done) { return; }
                var elt = document.getElementsByTagName('html').item(0);
                elt.className += (0 === elt.className.length ? ''  : ' ') + token;
                arguments.callee.done = true;
            };
            if (document.all && img.complete) {
            // this should fix reload (and back) button weirdness in IE/Win
                img.onload();
            }
        })('img');
        // ]]>
        </script>
    </head>
    <body>
    <div id="foo">
    Hello World!
    </div>
    </body>
    </html>
    
  30. December 4, 2007 by Roger Johansson (Author comment)

    Ed:

    Considering the implications of replacing a header with an image, is it not a case of the wrong tool for the job?

    It often is. But when you for one reason or another are forced to use image replacement it is good to be aware of which options cause the least problems.

    Carl:

    Your yawn is duly noted.

    Please don’t take my hesitance towards using img elements to replace text as saying that your method is a bad one! It’s just that I prefer other options.

  31. I know that Opera does enlarge and embolden alt text that is contained within an [h…] tag, and I think Firefox does as well, but I’m not sure. IE6 certainly does not.

    It does when images are turned off rather than broken, which I consider to be a much more relevant scenario.

  32. I believe in Petr Staníček and Tom Gilder’s Cover-up method. Yes, you need to introduce an empty span, but that’s a very small price for almost perfect accessibility.

  33. RE the BIR method mentioned above…

    Bangs head on wall…

    I came up with the exact same thing several years ago, but had no way of testing it with a screen reader at the time, so gave up assuming I’d probably missed some important point!

    Fame - missed it again. :(

    I’ve used the Gilder/Levin method a couple of times however.

  34. December 13, 2007 by alantext

    Roger, thank you for sharing your reasoning and your choice. I thought I would share my approach, which uses an IMG element within the heading element. Here’s why:

    I couldn’t use Gilder/Levin Method because it doesn’t work with transparent images and the site I was creating required transparent images. I also didn’t like the extra empty span in Gilder/Levin. Many of the methods don’t solve images off/css on, which as Roger says may be common for dial-up users.

    One thing the various CSS image replacement techniques have in common is that the image is coded as a CSS background image. I decided that it is acceptable to code the image in the HTML, since the image is an important piece of content in this case.

    Here’s what I did:

    • Hx has text content replicating the graphical image text.
    • IMG is a child of Hx element.
    • IMG has alt text replicating the graphical image text.
    • Negative text-indent to hide Hx text

    <H1><img src="Images/coffee.png" width="183" height="68" alt="coffee">coffee</H1>

    H1, H2 {text-indent: -5000px;}

    H1 IMG, H2 IMG {position: relative; left: 5000px;}

    Advantages of this method:

    • No extra elements are required.
    • Search engines have real live heading text to index.
    • In images off/css on situations, the user will see the alt text. Opera and Firefox render the alt text with the same size, colour and formatting as any other Hx on the site. (IE6 does not, I don’t know about IE7.)

    It may not be for everyone, but for a situation which requires transparent images I think this is a good solution that resolves many issues.

  35. I found very clever the NIR method that was mentioned in comment #7.

    Benefits:

    • no additional markup

    • solve image-off/css-on problem for all browsers except IE

    Downsides:

    • needs special part of CSS especially for IE (hacks or conditional comments can be used)

    • IE still have problem with image-off/css-on

    • IE for Mac not supported

    I have tested many browsers and got following results:

    Works as intended:

    • Firefox 1-3

    • Opera 7-9

    • Safari 1-3

    • Mozilla

    Works, but has image-off/css-on problem:

    • Internet Explorer 5-7 (Win)

    Degrades gracefully:

    • Opera 6

    • Internet Explorer 4 (Win)

    Doesn’t work (shows nothing):

    • Internet Explorer 5 (Mac)
  36. The one problem not mentioned here is printing. Lots of people actually print out websites — I know sacrilege — and most browsers don’t print background images unless you specifically tell them to.

    Since most people don’t touch settings, you should assume that the image won’t print. If this is an important image — like your logo — you should not be using image replacement.

  37. January 8, 2008 by alantext

    The printing issue is a good point. That was one of the reasons that I used the method I described above, which uses an IMG element within the heading element. I saw that many users were printing pages from the site, so I wanted to ensure that they would be able to print the heading images.

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.