¶ 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.







Comments
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.
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.
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.
4
I’m having second thoughts.
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.
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.
6
Unfortunately this won’t work with
offsetWidthbecause 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
offsetWidthis thecalculatedStyle()method but I discounted this because it is not supported by IE/Win.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/
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> ?
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.
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.
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.
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.
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.
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…
15
Hey, that’s a COOL hack man !! :)
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
*/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.
18
Nice. Came up with a variation of the theme using Gilder/Levin and a JavaScript function to inject those extra span tags.
Add your comment
Comments are now closed on this post. If you have more to say please contact me directly.