Published in Brighton, UK

Clagnut

JavaScript-enhanced image replacement

Most image replacement (IR) techniques work by displaying a background image of text and shifting the real text out of view. This is fine unless you have images turned off, in which case you will see neither the graphical text nor the real text.

So the requirement is to disable the IR if images are turned off. This can be accomplished by a short piece of unobtrusive JavaScript supplementing existing IR techniques:

function checkImages() {
  if (document.getElementById) {
    var x = document.getElementById('logoimg').offsetWidth;
    if (x != '134') {
      document.getElementById('heading').style.textIndent = "0";
    }
  }
}

The checkImages() function should be called by a window.onload handler. The function determines whether images are turned off by checking the offsetWidth of an existing inline image – the logo in this case. If the offsetWidth of the image element does not equal the known width of the image then images are assumed to be turned off and the IR technique (Phark in the case) is reversed to reveal the heading text.

You can see the script in action in my sandbox. I’ve also highlighted some of the known issues, so please have a read of those before commenting.

Related photos

  • Dang-Me
  • \'My\' new book
  • Web Accessibility: Web Standards and Regulatory Compliance

Next

Previous

Related posts

Keywords

Machine tags

Comments

  1. 1

    That’s a neat idea but how about this: Don’t wait for onload and immediately add an image to the page using createElement. Then attach an onload event handler to that new element that classes the html element with something like “has-images”. Then in your CSS prefix all of your text replacement selectors with .has-images.

    If the image never loads the classing never occurs thus removing the requirement that JavaScript be enabled to disable image replacement.

    Shaun Inman
    Shaun Inman’s Gravatar
    12 May 2005
    13:19 GMT
  2. 2

    Pretty good Shaun, pretty good. [As I’m quite sure you’re aware] there’s a number of different ways of trying to determine whether images are on and, as per your suggestion, attaching an onload event handler to an image is probably the best bet.

    The issue I had with that approach was that I wanted to run a function when images didn’t load, not when they did. But you’ve just found a way around that, and I thank you.

    Rich
    Rich’s Gravatar
    12 May 2005
    13:34 GMT
  3. 3

    Rock on. Here’s a quick proof of concept I threw together. It works in Safari, Firefox (Mac/PC), Opera, IE 6 PC, IE 5 Mac and intermittently in IE 5.x PC while failing silently in NN 4.x. I’m going to leave it at that (I’m sure the IE PC 5.x issues could be resolved with just a little elbow grease but this is just a proof of concept).

    The main reason for my alternative is that the current approach starts with image replacement enabled and assumes that JavaScript will be present to disable it if images are disabled. Someone surfing with images off may very well have JavaScript disabled too.

    Of course it works both ways, with my suggested approach you’re requiring JavaScript be enabled to “turn on” the image replacement. Pick your poison I guess.

    Shaun Inman
    Shaun Inman’s Gravatar
    12 May 2005
    14:00 GMT
  4. 4

    I’m having second thoughts.

    If the image never loads the classing never occurs thus removing the requirement that JavaScript be enabled to disable image replacement.

    That’s true but conversely it means that you need Javascript enabled in order to have image replacement, which is the problem I was trying to overcome. I suppose it really depends on where your priorities lie.

    Rich
    Rich’s Gravatar
    12 May 2005
    14:00 GMT
  5. 5

    I would agree that requiring javascript to turn on the replacement method is probably the better way to go. I just have an assumption about people who surf with javascript turned off, and that assumption is that they want as little window dressing as possible. We take the same stance in sIFR and it seems to work pretty well. If someone has gone through the trouble of manually turning off js, they’ll probably be fine with plain text.

    Also, I suggest that possibly checking for an image width of “greater than zero” might be a better long-term solution than checking for a specific width. That way, if you ever change the width of whatever image you’re checking, it won’t break things. This is a method we use a lot in Flash to make sure images or swfs have loaded. Seems to work pretty well.

    Cheers, and thanks for posting this. Very helpful. I can already think of a project which could use your script block.

    Mike D.
    Mike D.’s Gravatar
    12 May 2005
    15:33 GMT
  6. 6

    Also, I suggest that possibly checking for an image width of greater than zero might be a better long-term solution than checking for a specific width.

    Unfortunately this won’t work with offsetWidth because the image element still takes up space for the broken image icon or the alt text or both, so the returned value is always greater than 0.

    An alternative to offsetWidth is the calculatedStyle() method but I discounted this because it is not supported by IE/Win.

    Rich
    Rich’s Gravatar
    12 May 2005
    16:16 GMT
  7. 7

    I came up wih an alternative method for detecting if images are enabled:

    http://richardathome.no-ip.com/index.php?article_id=311

    The solution is down in the comments – a demo is here:

    http://richardathome.no-ip.com/examples/imagesEnabled/

    Richard@Home
    Richard@Home’s Gravatar
    13 May 2005
    09:03 GMT
  8. 8

    WOW, saves me using <span></span> all of the time… because im a dumbass anyone want to generate a version that supports multiple image replacements on a page e.g. 1x<h1> 2x<h2> ?

    mark rush
    mark rush’s Gravatar
    13 May 2005
    09:23 GMT
  9. 9

    Richard – that’s precisely the method I came up with too. Creating an image in the DOM and attaching an onload event handler seems a good way to execute a function if images are on.

    However I had it in my head that I wanted to execute a function if images were off. Hence my approach with this script.

    Rich
    Rich’s Gravatar
    13 May 2005
    09:46 GMT
  10. 10

    Quite a clever approach, very interesting!

    Huh, some kind of house advertising for the German readers: I just published a comprehensive overview of all (popular) Image Replacement techniques which covers almost all methods – I will include Richards idea as well. Feedback is appreciated.

    Jens Meiert
    Jens Meiert’s Gravatar
    14 May 2005
    15:28 GMT
  11. 11

    I think a better way to handle this would be to manipulate the CSS in the style sheet. Consider a scenario where you have more than one image replaced heading in the page, you might end up with CSS like

    h1.ir, h2.ir, h3.ir { text-indent:-999em; }

    Well if you manipulated the CSS for the page and not an individual element, it’d apply for all headings that you class as ‘ir’.

    Just a thought.

    Al.

    Alistair
    Alistair’s Gravatar
    15 May 2005
    03:57 GMT
  12. 12

    Why is this even neccesary to you?

    I mean, the alt attribute can easily be used for the text, which has to be shown, if images are disabled. In addition, the parent element can style this text through CSS.

    No need for JavaScript, and a fully accessible website.

    Troels Thomsen
    Troels Thomsen’s Gravatar
    17 May 2005
    09:35 GMT
  13. 13

    Troels – there are two points to address here. Firstly this post presents a solution to accessibility shortfalls inherent in existing techniques in (relatively) common use on live sites today.

    Secondly no image elements are used in the technique, so no alt text can be shown, and yes CSS can be used to style text but only in very basic ways and for most designers (and their clients) that is quite simply not good enough.

    For more on image replacement techniques, the whys and hows, I recommend Dave Shea’s image replacement summary.

    Rich
    Rich’s Gravatar
    17 May 2005
    09:51 GMT
  14. 14

    The problem with the other bits of code (Shaun & Richard@Home), is that it doesn’t work for me – I have both JavaScript and images enabled, but Shaun’s gives nothing and Richard’s says I have them disabled. I’m using yesterday’s build of Firefox, so it’s not like I’m on some obscure browser. The one in the article works correctly, though

    Maybe it’s just a bug because I’m on a nightly, but still…

    jordan
    jordan’s Gravatar
    17 May 2005
    17:41 GMT
  15. 15

    Hey, that’s a COOL hack man !! :)

    Balakumar Muthu
    Balakumar Muthu’s Gravatar
    18 May 2005
    12:27 GMT
  16. 16

    Great technique here, which I only just got around to using. I’ve thrown in my own tweak below, which classes the html element if images aren’t detected. This means that you can cancel styles in the CSS by prepending the “.noimgs” class selector, e.g.:

    /*
    newsection

    newsection

    */
    h2 {
    /* replacement gubbings*/
    text-indent: -9999px;
    }

    .noimgs h2 {
    text-indent: 0;
    }

    /*
    newsection

    newsection

    */

    This avoids styling getting tangled into your JS. My amended JS code below:

    /*
    newsection

    newsection

    */
    function checkImages() {
    if (document.getElementById) {
    var x = document.getElementById(‘bgimg’).offsetWidth;
    if (x != ‘1’) {document.getElementsByTagName(‘html’)[0].className = “noimgs”;
    }

    }
    }

    /*
    newsection

    newsection

    */
    Simon
    Simon’s Gravatar
    9 Jun 2005
    13:25 GMT
  17. 17

    Simon – thanks for that. Setting classes rather than styles is definitely the best way to use JavaScript, otherwise presentation ends up in the behaviour layer. A deliberate oversight on my part for the sake of simplicity.

    Rich
    Rich’s Gravatar
    11 Jun 2005
    17:53 GMT
  18. 18

    Nice. Came up with a variation of the theme using Gilder/Levin and a JavaScript function to inject those extra span tags.

    Mr.Khmerang
    Mr.Khmerang’s Gravatar
    18 Jun 2005
    02:33 GMT

Add your comment

Comments are now closed on this post. If you have more to say please contact me directly.

Outside interest

Top Referrers