Preloading On-Demand Images with CSS
Onmouseover and onfocus events in JavaScript, and :hover and :focus pseudo element actions using CSS, open up a world of interactivity on the web for both mouse and keyboard users alike using most browsers. (I wrote most browsers because IE doesn’t recognize the pseudo element :focus and must use :active, and that’s only on anchors.) Font colors can change, backgrounds can change, static images can be replaced with new images. In fact, swapping out imagery can be the root of some of the more creative uses. But like everything, the more you offer means the more it can cost in terms of user resource demands and smooth interactivity.
This is key, because if these events or actions trigger flashes or halted motions, it can detract from what would ordinarily be a pleasurable user experience. This is especially true when it comes to swapping out images for the simple reason that images must load to be viewed. With respect to web users without fast connections like broadband or quality DSL, simple actions like swapping out images via JavaScript or CSS can lead to some horrendous effects. Take, for instance a link with a static grayscale image background that’s meant to deliver a color background image when the user hovers over or focuses on it. Ideally we want this transition to be instantaneous. The last thing we want is to have the image begin loading at this point. Thus we need to preload the secondary image.
This can be done using a JavaScript preloading technique, a good method if JavaScript is supported. Another method, using CSS, employs a single, multi-part image re-positioned differently depending on its state; this is a great method especially for block link backgrounds. And then there’s a way of getting this done using CSS with display:none but I think this technique is flawed in that it doesn’t really load the image — at least I couldn’t find it on my Page Info > Media list (using Firefox) when I tested this.
All these methods aside, though, beneficial or flawed, I’ve long had my own method of doing this with CSS that has its own benefits. My method is especially useful for larger images like mastheads or banners in that the technique serves two purposes. My method uses an absolutely positioned offset class to get the replacement image off screen and out of sight while still allowing it to be downloaded to the browser. Now using absolute positioning for preloading is not a new technique, but how I the incorporate the replacement image into mark-up may be unique.
A lot of developers offer background images as image replacement for text. It often looks better than plain text and it’s a nice site design method. I do this a lot myself. This way I don’t have to worry about the visitor having a particular fancy font- or type-face. Most of the time I offer a second image which is available on hover or on focus. I don’t do this here on my blog, but I do on the inner pages of my SeaBeast theme for example. (Hover over or click on the masthead image to see it change, then turn off styles to see the preloaded image sitting nicely at the top of the page). What I do in that case is offer the secondary image as an offset image embedded in the markup, right where the masthead should be. This method provides a decorative masthead image if styles aren’t supported all while effectively preloading the secondary image to reduce the halted load effect. This may be something some people will like while others will not. There are advantages and disadvantages, as follows:
Advantages
- Preloads the secondary image to allow for smoother interaction.
- Requires no user-side scripting support.
- Can provide an important identity element like a logo.
Disadvantages
- Embeds an image in the mark-up (some purists won’t like that).
- Supports only two images unless two offset techniques are combined.
- Width of image sets a minimum width of its parent(s).
The How-To
Here’s an example of how something like this can be marked up, there are many others ways to do this as is the case on my SeaBeast theme’s inner pages (linked above) where I included the image above of the jump links and heading element, but with this example you’ll get the idea and that’s what I’m after.
<-- XHTML -->
<h1><a href="/">
<img class="offset" src="images/masthead.jpg" width="760" height="200" alt="" /><br />
<span><-- (this span is for an image replacement technique) --></span> YourSite.com
</a></h1>
<-- CSS (for embedded image offset class only) -->
img.offset {
position : absolute;
top : -9000px;
left : -9000px;
}
Notes: The alt attribute is left null as the text is supplied directly beneath it if styles are off so it’d be redundant. The break <br />
is added to keep the text underneath the embedded image if styles are off.
Neal V responds:
Posted: September 15th, 2006 at 7:31 pm →
Nice, man. I’ve had that problem before, where the first image on a roll-over is spastic while the image loads.
My only problem, though, is that you are using, ahem, inferior (I think) image replacement. Don’t you know that BIR is where it’s at? Hmm, perhaps I should rename it to NIR, since I’ve dropped my old moniker.
Mike Cherim responds:
Posted: September 15th, 2006 at 8:58 pm →
You know what Neal, you’re right. I had forgotton all about that technique of yours, but I will say it here and now that you probably have the most functional, most semantic image replacement technique on the web. No matter how I slice it or dice it, it works
Not to self: Start using BIR (or NIR if that’s going to be an official adoption).
John Faulds responds:
Posted: September 17th, 2006 at 10:32 pm →
BIR actually seems to be close to the Gilder/Levin IR method but has a problem with the text sticking out when the text size is increased.
Both have probably been superceded by the Gilder Levin Ryznar Jacoubsen IR method.
Mike Cherim responds:
Posted: September 17th, 2006 at 11:31 pm →
I wonder, if BIR’s is given a large enough area to grow, and then apply
overflow:hidden
to cover beyond that space’s limitation, if that method still might be the best way to go. Granted, I didn’t read the entire article about the referenced method (which I need to do), but I thought I spotted something about placing the text in the light emphasis element,<em>
. If that is indeed the case, using BIR might be the most semantic. It seems to be such a simple method to apply using very little CSS. I’ll have to read up on that and study its merits.John Faulds responds:
Posted: September 18th, 2006 at 5:02 am →
Just had a quick test with overflow: hidden on the BIR method and it doesn’t seem to prevent the text appearing on text resize and actually makes the text appear above the image in FF in some situations.
The em is required if you’re concerned about your image replacement working in IE5Mac, otherwise you can use a span. Most of the other IR methods I’ve seen that use an extra element usually involve it being empty, so in those cases I don’t see an empty em as being any less semantic than an empty span.
Mike Cherim responds:
Posted: September 18th, 2006 at 9:41 am →
Hey that’s cool. Thanks for testing that, John.