Bjørn Enki’s web design blog

Preload rollover images without any extra CSS or Javascript

Using alternate background images for "active" elements, or when hovering over an element is extremely common. In changing the image, however, unless precaution is taken, a flicker or delay is to be expected while the alternate image is loaded. I often use a single image that contains many possibilities and simply shift it's position around using CSS depending on the specific button in my custom website designs.

Preload rollover images without any extra CSS or Javascript

The problem

Using alternate background images for "active" elements, or when hovering over an element is extremely common. In changing the image, however, unless precaution is taken, a flicker or delay is to be expected while the alternate image is loaded. I often use a single image that contains many possibilities and simply shift it's position around using CSS depending on the specific button in my custom website designs.

Overview

JavaScript has been the norm in the past to deal with preloading images, and a number of CSS methods have surfaced over the last several years. However, JavaScript solutions (apart from depending on JavaScript) require relatively large and cumbersome amounts of code to be added to a page/site. On the other hand, CSS methods usually introduce content into a page that is never intended to be seen - for the sole purpose of preloading it - which of course isn't very semantically correct.

Although the following seems by far to be the best solution to me, surprisingly, I rarely see this technique in use.

The technique

The header in use in my (old) website used to require 21 images  (7 categories, each with 3 states.) This meant 70KB of downloaded images, but much worse, 21 http requests. Using my new technique, each of the 7 buttons and all 3 of their states are contained in one single 15KB image. This means I went from 21 requests to 1, and from 70KB to 15KB, all in one technique.

Basically, rather than having a single image for each state of the 7 buttons in my header, I use a single image that contains all possibilities and simply shift it's position around  using CSS depending on the specific button. Here's a slightly shrunk version, for example:

Here's the one image:

An image of my old header navigation sprite

 

The accompanying CSS

 
.slider a { background:url(header-icon-strip.png); }
    #nav-services a { background-position:-60px 0px; }
    #nav-services a.on { background-position:-60px -54px; }
    #nav-services a:hover { background-position:0px 54px; }

    #nav-portfolio a { background-position:-210px 0px; }
    #nav-portfolio a.on { background-position:-210px -54px; }
    #nav-portfolio a:hover { background-position:-150px 54px; }

    #nav-testimonials a { background-position:-360px 0px; }
    #nav-testimonials a.on { background-position:-360px -54px; }
    #nav-testimonials a:hover { background-position:-300px 54px; }

    #nav-blog a { background-position:-510px 0px; }
    #nav-blog a.on { background-position:-510px -54px; }
    #nav-blog a:hover { background-position:-450px 54px; }

#nav-articles a { background-position:-660px 0px; }
    #nav-articles a.on { background-position:-660px -54px; }
    #nav-articles a:hover { background-position:-600px 54px; }

   #nav-payinvoice a { background-position:-810px 0px; }
#nav-payinvoice a.on { background-position:-810px -54px; }
#nav-payinvoice a:hover { background-position:-750px 54px; }

#nav-contact a { background-position:-960px 0px; }
#nav-contact a.on { background-position:-960px -54px; }
   #nav-contact a:hover { background-position:-900px 54px; }  
 

As you can see in the CSS, the same background image is used for all buttons and each of their states - it's merely shifted around using the background-position attribute of CSS. There's no more code necesary and my users and server are both saved 20 http requests and a chunk of unnecessary preloading code.

This technique is tested and works as expected in IE6+, Firefox, Safari, Chrome and Opera.

Posted May. 21, 2009 at 4:48 pm under: website development, css, javascript

Comments

Duncan, Nov. 22, 2009 at 8:55 am
Excellent solution, by far the best. Once I had seen this I realised this it is exactly what Google do with their search engine results. Thank you very much!
Michael Montgomery, Sep. 14, 2009 at 4:44 am
Hi Bjorn, THX for this short explanation. Concise and to the point. Cheers
Bjorn Enki, Aug. 2, 2009 at 9:26 pm
That's great to hear, thanks Ben!
Ben Frain, Jun. 27, 2009 at 3:52 pm
Hello, thanks for posting this up. I think it's absolutely genius in its simplicity and function. Seriously very impressed. Well done. Can't wait to give it a whirl on a site soon.
Leave a response!