Latest TweetsVerify any search engine or visitor via CLI Forward-Reverse Lookup perishablepress.com/cli-forwar…
Perishable Press

Better Image Caching with CSS

I have written previously on the fine art of preloading images without JavaScript using only CSS. These caching techniques have evolved in terms of effectiveness and accuracy, but may be improved further to allow for greater cross-browser functionality. In this post, I share a “CSS-only” preloading method that works better under a broader set of conditions.

Previous image-preloading techniques target all browsers, devices, and media types. Unfortunately, certain browsers do not load images that are hidden directly (via the <img> element) or indirectly (e.g., via the parent <div> element) using either display:none; or visibility:hidden;. Further problematic is the potential unintentional display of images on pages when presented via specifically designed print stylesheet.

To get around these limitations, we begin by segregating our strategy to target different media types. For example, for web pages featuring both screen and print stylesheets, we treat each separately by writing this:

@media screen {}
@media print {}

Then, to ensure that the images are preloaded in all browsers, we need to avoid the use of either display:none; or visibility:hidden; in the method. Rather than risking non-caching by hiding or preventing the display of images that need preloaded, we ensure their display and position them far outside of the screen. To do this, we enclose all images that need cached within some specifically identified division like so:

<div id="preloader">
	<img src="http://domain.tld/path/images/01.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/02.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/03.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/04.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/05.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/06.png" width="1" height="1" />
	<img src="http://domain.tld/path/images/07.png" width="1" height="1" />
</div>

Then, with that markup in place, we flesh out the previous media directives with the following CSS:

@media screen {
	div#preloader {
		position: absolute;
		left: -9999px;
		top:  -9999px;
		}
	div#preloader img {
		display: block;
		}
	}
@media print {
	div#preloader, 
	div#preloader img {
		visibility: hidden;
		display: none;
		}
	}

Here, we have the preloader division positioned far to the lower-left outside of the screen, and then redundantly specify block display on the image elements.

Finally, to prevent the unwanted display of these preloaded images via print media, we simply hide the images via display:none; and visibility:hidden; declarations.

When using this method to preload/cache images, remember to call the preloaded images by using the exact same path used for the original preloaded image. For caching to work, the browser must reference an existing resource via the identical path.

This method is designed to enable the caching of specified images in virtually all visual browsing devices. If you encounter cases where this method does not work, or if you have comments or suggestions for improvement, please share by leaving a comment below. Thanks!

Jeff Starr
About the Author Jeff Starr = Fullstack Developer. Book Author. Teacher. Human Being.
Archives
45 responses
  1. Good article Jeff.

    One question: what’s the need for visibility:hidden on top of using display:none? Since it does the same as display:none, except for it still takes up white space while being invisible?

    Thanks.

  2. Jeff Starr

    Hi Jin, we are including both visibility:hidden and display:none to account for a broader range of application. Browsing devices handle CSS properties differently according to specific implementation. Using both properties may be redundant in some browsers, but covers the bases when one or the other is behaves unexpectedly.

  3. What a great article!

    I’m wondering if there should be some inclusion for handhelds. I think they would get a big block of images at the bottom (probably) of the page, which would also likely increase their initial download time, something which one assumes is wise to avoid for handheld devices. I don’t own a Blackberry and if my cell phone is on, it probably means there’s a tear in the space time continuum.

    Perhaps the @media print rule could read @media print,handheld?

  4. Good point Jeff. Thanks for the explanation.

  5. Hi Webbo,

    If you add all of these images in a div at the very bottom of the page (i.e. before the ending body tag), then the loading won’t be noticeable to users.

    @Jin:
    display:none and visibility:hidden are different in nature, in that the display property changes the flow characteristic of the element, whereas visibility doesn’t.

    When an element is set to visibility:hidden it is simply invisible and stops receiving events, the element will still be part of the document flow however and as such will still occupy space.

    When an element is set to display:none the element is removed from the flow and the following elements move to take its space.

  6. Sorry if this is a stupid question but I am new to this!!

    But if you preloading all the images this way will it not just slow down the load time of the 1st page? This would be more important to load quickly than subsequent pages.

  7. I tried this for a while, but I was concerned that people using text based browsers might be confused seeing so many images and perhaps feel like they were missing out on content.

    I’ve gone back to using sprites for design/interface elements.

    Anything else doesn’t really need caching.

  8. Nice writeup on image caching :) I didn’t realise the importance of the redundancy for visibility and display properties until I read through the comments. In the past when my layouts involve using multiple, small images/icons (usually a typical layout of mine will have around 20~30 images), I will preload them using Javascript in an array or something. Then when I became more well versed with CSS (and when my javascript started a downward spiral into oblivion), I used the visibility/hidden trick. It never came across me to use absolute positioning to make sure that they stay out of the page though :) that’s interesting!

    For the moment being I’ve decided that having too many images for a layout does not only make naming them a big problem, but also create unnecessary hassles for updates/migration. I hate jumping between the image folder and CSS (or notepad). I’ve settled for CSS sprites for now.

    But then again, a very informative piece of post on image caching! I love it that you’re using a purely CSS way to do that instead of incorporating another snippet of javascript (for some reason I try to avoid inserting too much javascripts into my pages). Call me a purist.

    p/s: Sorry to hear about the subscriber’s issue. Is it a bug or something?

  9. Hey i’m not going to repeat what others have said (except woohoo great article ;) )

    1) However say you move the theme / blog to a new server or location, This would require updating then right?

    2) Reading around i’ve noticed scripts that cache css js etc on the fly to a seperate directory (http://reinholdweber.com/); So was wondering could you set this as well with a similar principle? i.e. it caches ‘theme’ images and ‘post’ images in a similar manner. (I too love perofrmace :p)

    there are one two other points but i’ll get back to them after lunch and saying…new design?!;)

  10. Jeff Starr

    @Bill: Using @media print, handheld is an excellent idea. Great tip for optimizing mobile design!

    @webbo: To my knowledge, placing your preloaded images at the bottom of the page causes them to load after the remaining elements on the page. Thus, visitors will be able to view contents while images load in the background. This technique works great for slideshows and other thumbnail/full-size galleries.

    @Dan: Every design is unique and requires different strategies. Using sprites for slideshows and product pages may not be the optimal way to go. Preloading and caching images will definitely help in these scenarios.

    @teddY: Thanks for the great comment! I too am still learning about all the details and sorcery involved with preloading and caching images. Anything related to increasing performance is on my “favorite topics” list ;) Also, not sure about Feedburner, but I hope the higher count is restored! ;)

  11. I can’t recall where I initially read it but http://reinholdweber.com/?p=42 is where I last enquired about it :p

    and, here is the script (partial) http://reinholdweber.com/?p=37

  12. Jeff Starr

    @Donace: Yes, as with all markup, links, and images, if you relocate your site, the paths will change; and if they do, URL paths will need to be updated with the correct information. Throw me a link to the second topic you mention and I will have a look.. at the moment it’s not ringing any bells..

[ Comments are closed for this post ]