Save 10% on our Pro WordPress plugins with discount code: 10PERCENT
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="" width="1" height="1" alt="Image 01" />
   <img src="" width="1" height="1" alt="Image 02" />
   <img src="" 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.
USP Pro: Unlimited front-end forms for user-submitted posts and more.

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.
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 »
GA Pro: Add Google Analytics to WordPress like a pro.
Making great strides on my new book. Planned release in December :)
To organize my life, I keep it simple. online: plain text files, offline: sticky notes.
Official list of Googlebot IP addresses.
Lot of 1s in today’s date 20211111.
Working on a new book :)
I enjoy listening to original Star Trek and NG episodes while working online. After a while it feels like I’m working on the ship as part of the crew, going on adventures.
New version (2.6) of my shapeSpace starter theme now available! Always free & open source for everyone :)
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.