views:

1624

answers:

4

I'm fully aware that this question has been asked and answered everywhere, both on SO and off. However, every time there seems to be a different answer, e.g. this, this and that.

I don't care whether it's using jQuery or not - what's important is that it works, and is cross-browser.]

So, what is the best way to preload images?

A: 

Different answers don't mean there is A BEST WAY to do it, it can simply mean there different case, with different way to do it.

The best way will be the one that fit your needs !

Try them all, and choose.

Boris Guéry
The thing is though, I'm sure lots of people have done lots more cross-browser testing - I'm trying to not reinvent the wheel!
Skilldrick
+8  A: 

Unfortunately, that depends on your purpose. If you plan to use the images for purposes of style, your best bet is to use sprites. http://www.alistapart.com/articles/sprites2

However, if you plan to use the images in <img> tags, then you'll want to pre-load them with

function preload(sources)
{
  var images = [];
  for (i = 0, length = sources.length; i < length; ++i) {
    images[i] = new Image();
    images[i].src = sources[i];
  }
}

(modified source taken from http://stackoverflow.com/questions/761263/what-is-the-best-way-to-preload-multiple-images-in-javascript/761332)

using new Image() does not involve the expense of using DOM methods but a new request for the image specified will be added to the queue. As the image is, at this point, not actually added to the page, there is no re-rendering involved. I would recommend, however, adding this to the end of your page (as all of your scripts should be, when possible) to prevent it from holding up more critical elements.

Edit: Edited to reflect comment quite correctly pointing out that separate Image objects are required to work properly. Thanks, and my bad for not checking it more closely.

Edit2: edited to make the reusability more obvious

Jonathan Fingland
+1 for writing everything I was about to submit. Beat me by 25 seconds. :-)
Jesse Dearing
thanks for the +1 and glad I didn't try to make the grammar perfect before posting :)
Jonathan Fingland
Guess you didn't actually read the answer to the question you linked to. That method only preloads the last item in the array.
Crescent Fresh
What's the point of storing images in array here? IIRC, simply assigning url as a src of an Image should work just fine (and would result in lesser memory consumption).
kangax
kangax, the code as given is easily put into a routine for easy re-use. writing each one separately is much less reusable. see my edit
Jonathan Fingland
Well, I wasn't talking about putting it in a routine. I'm curious why you store Image objects in array.
kangax
@kangax I'm a bit late seeing your response, but the reason for the array of images is: A) if you re-use the same `Image` object then every time the `src` property is changed, the current one will be dropped (even if the download is incomplete), and B) if you create a new `Image` object but assign it to the same variable then you are just hoping the garbage collection doesn't spoil things for those now de-referenced `Image` objects. Arrays are cheap security against A and B.
Jonathan Fingland
+2  A: 

Spriting

As others have mentioned, spriting works quite well for a variety of reasons, however, it's not as good as its made out to be.

  • On the upside, you end up making only one HTTP request for your images. YMMV though.
  • On the down side you are loading everything in one HTTP request. Since most current browsers are limited to 2 concurrent connections the image request can block other requests. Hence YMMV and something like your menu background might not render for a bit.
  • Multiple images share the same color palette so there is some saving but this is not always the case and even so it's negligible.
  • Compression is improved because there is more shared data between images.

Dealing with irregular shapes is tricky though. Combining all new images into the new one is another annoyance.

Low jack approach using <img> tags

If you are looking for the most definitive solution then you should go with the low-jack approach which I still prefer. Create <img> links to the images at the end of your document and set the width and height to 1x1 pixel and additionally put them in a hidden div. If they are at the end of the page, they will be loaded after other content.

aleemb
I'd never thought of the 'low-jack approach'... nice idea, and so simple!
Dave Everitt