Better Image Preloading with CSS3

by Jeff Starr on Monday, January 4, 2010 31 Responses

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!

About the author

[ Jeff Starr ]

Jeff Starr is a web developer, graphic designer and content producer with over 10 years of experience and a passion for quality and detail. Jeff is co-author of the book Digging into WordPress and strives to help people be the best they can be on the Web. + Follow Jeff on Twitter and subscribe to Perishable Press for awesome web-design content delivered fresh.


31 Responses

Add a comment

[ Gravatar Icon ]

Kristi#1

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?

[ Gravatar Icon ]

Jeff Starr#2

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.

[ Gravatar Icon ]

Trav#3

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

[ Gravatar Icon ]

Jeff Starr#4

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.

[ Gravatar Icon ]

Chris Coyier#5

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.

[ Gravatar Icon ]

Steffan Williams#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.

[ Gravatar Icon ]

Rod Homor#7

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!

[ Gravatar Icon ]

Jeff Starr#8

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

[ Gravatar Icon ]

Ryan#9

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.

[ Gravatar Icon ]

Jeff Starr#10

@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 :)

[ Gravatar Icon ]

Alexandru Dinulescu#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.

[ Gravatar Icon ]

Jeff Starr#12

@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)?

[ Gravatar Icon ]

Alexandru Dinulescu#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.

[ Gravatar Icon ]

Jeff Starr#14

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

[ Gravatar Icon ]

Devilcantburn#15

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

[ Gravatar Icon ]

Jennie#16

@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

[ Gravatar Icon ]

Kartlos Tchavelachvili#17

-9999px > -999em

Write less do more :D

[ Gravatar Icon ]

Jeff Starr#18

@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 :)

[ Gravatar Icon ]

Richard Link#19

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.

[ Gravatar Icon ]

WSz#20

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 ;)

[ Gravatar Icon ]

Jeff Starr#21

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

[ Gravatar Icon ]

WSz#22

@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 ;)

Trackbacks / Pingbacks
  1. Twitter Trackbacks for Better Image Preloading with CSS3 • Perishable Press [perishablepress.com] on Topsy.com
  2. uberVU - social comments
  3. Descubrimientos del 5 Enero 2010 | Blog de unique3w
  4. Better Image Preloading with CSS3 — MooTools and CSS Resources
  5. Elsewhere, on January 7th - Once a nomad, always a nomad
  6. 50 Brilliant CSS3/JavaScript Coding Techniques - Smashing Magazine
  7. Rémi Garcia – Blog » Pré-charger ses images en CSS3 plutôt qu’en JS
  8. 50 Advanced CSS3 Techniques and Tutorials » DJDESIGNERLAB – Find All Your Design Inspirations From This Laboratory
  9. Even better image preloading with CSS2 | The CSS Ninja - All things CSS, Javascript & xhtml
Share your thoughts..

Read Comment Policy

Comment Rules: No spam. No profanity. Use your real name. You may use simple HTML tags for style. Wrap all code in <code> tags. Learn more.



Attention: Do NOT follow this link!