Better Image Preloading with CSS3

Posted on January 4, 2010 in Function, Presentation by

I recently added to my growing library of image-preloading methods with a few new-&-improved techniques. After posting that recent preloading article, an even better way of preloading images using pure CSS3 hit me:

.preload-images {
	background: url(image-01.png) no-repeat -9999px -9999px;
	background: url(image-01.png) no-repeat -9999px -9999px,
		    url(image-02.png) no-repeat -9999px -9999px,
		    url(image-03.png) no-repeat -9999px -9999px,
		    url(image-04.png) no-repeat -9999px -9999px,
		    url(image-05.png) no-repeat -9999px -9999px;
	}

Using CSS3’s new support for multiple background images, we can use a single, existing element to preload all of the required images. Compare this method with the old way of using CSS to preload images:

.preload-01 { background: url(image-01.png) no-repeat -9999px -9999px; }  
.preload-02 { background: url(image-02.png) no-repeat -9999px -9999px; }  
.preload-03 { background: url(image-03.png) no-repeat -9999px -9999px; }
.preload-04 { background: url(image-04.png) no-repeat -9999px -9999px; }
.preload-05 { background: url(image-05.png) no-repeat -9999px -9999px; }

As you can see, the CSS3 method is a much cleaner way to preload your images using a single CSS selector. Note that we’re also going to need to ensure the background images aren’t being displayed in the preload element. For that, I suppose we could either hide the element using display:none or else position the images far off screen using -9999px positioning.

Pros

This technique works great in supportive browsers now, and the support will only get better moving into the future. Notice that we can include a partial fallback mechanism by preloading one of the images as a single background property value. Browsers that don’t get the multiple stuff will fallback to the single-value background property instead.

Also, browser support for CSS is much better than for JavaScript, so big improvement there. Beyond these things, the sheer ease of picking an element and adding all of our preload images as backgrounds is simply too easy not to take advantage.

Cons

Well, let’s see.. current browser support is not as good as it could be, mostly because of Internet Explorer. So besides the fact that IE may never understand multiple background-images, the downsides to using this method are pretty much nil as far as I can tell. Perhaps I am missing something completely obvious..? Maybe someone will elaborate on the non-presentational use of CSS? ;) Chime in!

Related articles

24 Responses

  1. [ Gravatar Icon ] Kristi says:

    This is clever. Non-semantic markup makes me cringe, but I prefer it to unnecessary JavaScript. How does this method affect the perceived loading time of the visible images on the page?

  2. [ Gravatar Icon ] Jeff Starr says:

    Not sure, but I think that CSS images are loaded according to their position within the stylesheet. So by placing the preloading selector at the bottom of the CSS file, all other images should load first.

  3. [ Gravatar Icon ] Trav says:

    I like it, very clean. The only thing still making me nervous is all of those http calls- I’d be tempted to merge them into a single sprite, especially if they’re ‘layout’ graphics, and not editorial. Happy New Year!

    Trav

  4. [ Gravatar Icon ] Jeff Starr says:

    Yes, good point. I think that merging your background images into as few sprites as possible is a good idea, but they already will be loaded from their actual display selectors, so no need to preload them. I think this technique is best for editorial/gallery images, but keeping in mind the overall number of HTTP requests is definitely wise.

  5. [ Gravatar Icon ] Chris Coyier says:

    I had some preloading CSS3 thoughts as well… using pseudo selectors like :after to attach background images. That way you could actually use the same selector you are probably preloading the image for, so the stylesheet would be cleaner. Alas, in my testing, it didn’t want to preload images using :after… but my testing wasn’t very extensive.

  6. Very nice indeed.

    @Kristi, it doesn’t have to be non-semantic though, right? All you have to do is apply the proposed class to any element on your page that you don’t want a background image on.

    It’s a nice way, moving forward, as more browsers support CSS3. Not sure if I’d opt for it myself, currently, but its still nice.

  7. [ Gravatar Icon ] Rod Homor says:

    Pretty interesting idea. I may give it a whirl on a smaller project just to see how it works in practice, and not just as a theory. But, again, very interesting idea. Thanks!

  8. [ Gravatar Icon ] Jeff Starr says:

    @Rod: you know it will - it’s all just a theory even when it works :)

  9. [ Gravatar Icon ] Ryan says:

    Good example but the browser support isn’t that great with mutiple backgrounds at the moment. I did a post on preloading images using the CSS2 content property which allows me to preload multiple images in the 1 line of CSS http://www.thecssninja.com/css/even-better-image-preloading-with-css2.

  10. [ Gravatar Icon ] Jeff Starr says:

    @Chris: good idea using the :after pseudo-selector to provide more flexibility. I will do some experimenting and see if there is a good cross-browser way of using it for preloading.

    @Ryan: that looks like a great way of doing it with CSS2.1 - thanks for sharing :)

  11. Does this technique works for background images?
    For ex:
    I have in my css a large background-image: url("./img.png"); that is accessed when i switch the class of an item via javascript. If i dont have the website cached, instead of loading that image at the beginning and then taking it from the cache and applying on the element it just loads it again.
    So this thing does not work for background images.

    It may only work for images that are in the tag.

    If i am wrong please correct myself, because from what i tested on my website i couldnt figure a way to do this.

  12. [ Gravatar Icon ] Jeff Starr says:

    @Alexandru: are you sure the same image is being called using the (exact) same path? also, you say, “if I don’t have the website cached..” - does that mean that the results are different in the other case (when the browser is primed)?

  13. @Jeff lets me explain a bit.

    I am using a jQuery stylesheet changer on my blog which changes the “look” of my website. Now things happened like this, i removed the css because of multiple http requests to the server and download the images again and again, i should only have the CSS load for the main-page homepage only rather than for all the pages.

    Both the change-theme menu and the different images for each theme are loaded also when the user enters the website. I looked with firebug in the NET category. Now let’s say the user wishes to change the theme from the default to something else. He clicks on the start menu icon -> change theme -> and when the menu loads he doesnt have the background image already cached and it downloads it again, EVEN THO IT WAS REQUESTED WHEN THE USER FIRST LANDED ON THE PAGE. I dont have to mention the theme images not being loaded at all, but i do have in my firebug calls for those images at the start.

    The paths are either relative like “./images/theme1/img1.png” and i have tried with absolute like http://alexdweb.com/blog/wp-content/themes/inanisMod/images/theme1/img1.png and both methods have not yeilded results.

    Hopefully i could make myself rather clear. If you want i can give you a live example.

  14. [ Gravatar Icon ] Jeff Starr says:

    @Alexandru: perhaps there are some expiration and/or caching rules being applied to the images via HTAccess or elsewhere? It sounds like something may be telling the browser to not cache the images.

  15. Good technique… I use it sometimes as it does not function anywhere…

  16. [ Gravatar Icon ] Jennie says:

    @Alexandru, Jeff

    have come across this issue when loading in font-face files

    * IE will download the file immediately when it encounters the css declaration.

    * Gecko, Webkit, and Opera all wait until they encounter HTML that matches a CSS rule

    full explanation here
    http://paulirish.com/2009/fighting-the-font-face-fout/

    HTH

  17. -9999px > -999em

    Write less do more :D

  18. [ Gravatar Icon ] Jeff Starr says:

    @Jennie: thanks for the link - I will savor the details of that post. What do you think is the optimal workaround for this issue?

    @Kartlos: Nice :)

  19. [ Gravatar Icon ] Richard Link says:

    I’ve been thinking about this for a while, and once I get some time, I will probably implement this idea.

    Personally, I do many things at once, and having one web browser suck all the available connections/bandwidth seems greedy to me, and also creating many image objects seems that it would bloat the memory footprint of a particular page.

    The idea I had was to have a script that would accept the list of images to preload, and using one image object, load them sequentially.

  20. [ Gravatar Icon ] WSz says:

    Using CSS sprites really negates using preloaders, and I’ve long stopped using them. Sure mobile browsers (I’m looking at you Safari) still have a ways to go to render them properly, but still ;)

  21. [ Gravatar Icon ] Jeff Starr says:

    @WSz: For design elements, yes, but not so for preloading gallery images, shopping carts, and so on. Very difficult to configure as CSS sprites ;)

  22. [ Gravatar Icon ] WSz says:

    @Jeff,

    I’ve always used js galleries and let them respectively preload the images, but I’m thinking it wouldn’t be that hard to map out a CSS3 gallery using sprites. I have a concept in my head that can be done using jquery, but maybe it’s possible to do it even without js. Maybe a project for a rainy Sunday?

    I’ve never done an e-commerce website so can’t comment on shopping carts ;)

    PS: oh, and while I really dig the design of your website, I do have a problem with the “Submit Comment” button: It looks like an input field and not an actual button. As raw usability goes, that’s not a good thing ;)

  23. [ Gravatar Icon ] nev says:

    Why not just use display:none ?

  24. [ Gravatar Icon ] Jeff Starr says:

    nev - great question.. I’m thinking that using display:none causes problems for some browsers.. (but it’s been awhile)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Please use basic markup. Wrap code with <code> tags!