Welcome to the new design! Please report any bugs or issues, thanks :)
Web Dev + WordPress + Security

Pure CSS: Better Image Preloading without JavaScript

[ Preload Images with CSS ] After reading my previous article on preloading images without JavaScript1, Nanda pointed out that adding extra markup to preload images is not the best approach, especially where Web Standards are concerned. Mobile devices, for example, may experience problems when dealing with the following preloading technique:

div#preloaded-images {
   position: absolute;
   overflow: hidden;
   left: -9999px; 
   top: -9999px;
   height: 1px;
   width: 1px;

<div id="preloaded-images">
   <img src="https://perishablepress.com/image-01.png" width="1" height="1" alt="Image 01" />
   <img src="https://perishablepress.com/image-02.png" width="1" height="1" alt="Image 02" />
   <img src="https://perishablepress.com/image-03.png" width="1" height="1" alt="Image 03" />

Thus, as Nanda suggests, it is better to preload images using only CSS. Using the CSS background property, we can preload images via existing <div>s, <span>s, or other elements in the (X)HTML markup.

Let’s say you have three images (e.g., image_01.png, image_02.png, and image_03.png) that you would like to preload using this method. First, examine your markup for three identifiable <div>s (or other elements) that may be used as CSS hooks for the preloaded images. For example, looking at the source code of the current page, I would choose the following three divisions:

  • <div id="wrap">...
  • <div id="jump">...
  • <div id="header">...

Then, to implement the preload, I would add the following code to my site’s CSS file:

div#wrap {
	background: url(image_01.png) no-repeat -9999px -9999px;
div#jump {
	background: url(image_02.png) no-repeat -9999px -9999px;
div#header {
	background: url(image_03.png) no-repeat -9999px -9999px;

Here, we are preloading each image into its own unique <div> and then preventing its display by positioning it to the far left of the browser window. If the preloading elements are empty with no discernible height or width, hiding the preloaded images off-screen should not be necessary because they will not be displayed. Even so, it is probably a good idea to relocate them just to be safe.

Of course, once you have implemented this code to preload your images, they will be immediately available (depending on size) for display in your document as needed. Simply refer to them as normal using whatever CSS code that you would normally use. For example, once these images have preloaded, I could employ the following :hover technique with minimal presentational delay:

a#first:hover {
	background: url(image_01.png) no-repeat 50% 50%;
a#second:hover {
	background: url(image_02.png) no-repeat 50% 50%;
a#third:hover {
	background: url(image_03.png) no-repeat 50% 50%;

According to my tests, this technique works well in any browser (including IE 6) that supports the CSS background property. Best of all, this preloading method is entirely unobtrusive, requiring no presentational code and degrading gracefully in non-supportive browsers.


Jeff Starr
About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
WP Themes In Depth: Build and sell awesome WordPress themes.

29 responses to “Pure CSS: Better Image Preloading without JavaScript”

  1. And what if you’d like to preload the images for a slideshow, that will be started as soon as all of the images are loaded? (Or at least the next one.) How can it be checked? I do not know the solution, but I guess that it won’t work in this “CSS-way”. So maybe it is not the best solution. :(

  2. Jeff Starr
    Jeff Starr 2010/11/04 8:16 am

    Hi Swirlsky, you’re probably better off using JavaScript or even Flash for a decent slideshow experience. I have also read that in HTML5, you can use next and previous-image meta-tags in the header to tell the browser which images to fetch next. Totally unsure about the functionality and support for that, but it may also be something worth checking out.

  3. Does anyone have an aversion to the following technique?

    #imagePreloader { display:none; background:url(images/image1.jpg); background:url(images/image2.jpg); background:url(images/image3.jpg); background:url(images/image4.jpg); background:url(images/image5.jpg); background:none; }

  4. Jani, I’m no expert, but that method seems to depend on the behavior of the user agent. IOW, the browser must (1) load multiple, repeated backgrounds and not the first or last only, and (2) further override the url()s with ‘none’. While it may work, it would require testing and I’m guessing isn’t defined behavior in the standard.

    I was thinking, though, that it might be more elegant to use classes, e.g.:

    div#preload { display: none; }
    div#preload.1 { background-image: url(...) }
    .2 { background-image: url(...) }
    .3 { background-image: url(...) }

    IIRC, the ID will override the class, being more important, but the multiple classes should all get applied. I haven’t tested this, just a thought.

  5. Thanks Jeff, works great for background hovers

Comments are closed for this post. Something to add? Let me know.
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
The Tao of WordPress: Become your own WordPress guru.
Super useful post about making custom avatars in WordPress.
Making good progress on the new bookstore subdomain here at Perishable Press. Aiming for launch early Summer :)
Playing the long game.
They have weaponized the idiots.
Good software never steals focus from the user. Even during startup.
After 10 years running my own business, I still manage schedules and tasks using old school post-it notes, sometimes simple sometimes very elaborate.
You know those sites, where you're trying to just grab a quick bit of information but the page is shifting all over the place as it loads up 3 million advertisements.