Fall Sale! Code FALL2024 takes 25% OFF our Pro Plugins & Books »
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:

/* ADD THIS TO CSS */
div#preloaded-images {
   position: absolute;
   overflow: hidden;
   left: -9999px; 
   top: -9999px;
   height: 1px;
   width: 1px;
}

<!-- ADD THIS TO XHTML -->
<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" />
</div>

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.

Footnotes

About the Author
Jeff Starr = Designer. Developer. Producer. Writer. Editor. Etc.
SAC Pro: Unlimited chats.

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 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.
Welcome
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 »
USP Pro: Unlimited front-end forms for user-submitted posts and more.
Thoughts
I disabled AI in Google search results. It was making me lazy.
Went out walking today and soaked up some sunshine. It felt good.
I have an original box/packaging for 2010 iMac if anyone wants it free let me know.
Always ask AI to cite its sources. Also: “The Web” is not a valid answer.
All free plugins updated and ready for WP 6.6 dropping next week. Pro plugin updates in the works also complete :)
99% of video thumbnail/previews are pure cringe. Goofy faces = Clickbait.
RIP ICQ
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.