Image preloading
by Cornelius Weidmann on 13 May 20142 min readImage preloading is actually quite simple and there are many ways to do it. I will be focusing on a technique that involves hiding the images and attaching a load event to them.
The end result can be viewed here: image preloader demo.
The first task is to grab all images within a container (background images, gradients and normal img tags). We will do this by running multiple .children()
functions on the selector to grab all its children, not only the first level children. We then check if the elements we selected are images or contain background images and get the relevant URLs that point to the images:
if (image.css('background-image') !== 'none') {
return image.css('background-image').replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
} else {
return image.attr('src');
}
The next step will be to count the image elements to see how many images we need to preload. This will give us a very basic guideline for calculating the percentage loaded. If we want to get the exact percentage (instead of just dividing images loaded / total number of images) we can run a HEAD request for each image and get its file size by looking at the "Content-Length"
attribute.
By now you might be thinking, "Didn't the image elements already start their loading progress before we even got to preload them?". Well, if we were clever we would have hidden the image elements as soon as we detected them. Remember, when preloading we are not actually preventing the browser from downloading the images until we "preload" them. We are merely tracking the loading progress of the images and showing a progress bar of how the loading is going. We do this, because it does not make sense to prevent the image loading until we are "ready" to preload them. With preloading we simply control the behaviour of the images. We could for example reveal them as they become available or only once all images have loaded.
So once we've done the above we add a handler to the images to detect their load event. We do this with jQuery's .load()
function.
imageElements.forEach(function(element) {
var img = $('<img />').attr('src', element.imgUrl);
img.load(function() {
updateLoader(element);
}).error(function() {
updateLoader(element);
handleLoadingError(img, element);
});
});
As you can see in the snippet above we also update our loading percentage after each image has loaded. That already concludes basic preloading. From here on out it is up to you to add trickle speed and animation speed and pretty much any other enhancements you can think of.