Progressive image loading is here. It’s on the rise and for good reason, too. What is the progressive loading of images, you might be asking? It is the concept of offering up a low-resolution image upon initial page load, and then only after the high res version of the image has completed loading in the background, we provide the newly loaded substitute.
Let’s begin
First-things-first. We need something to contain our two images and hide any overflow. This will make sense later. We’ll give it a class name of .progressive-image.
Next we need the placeholders for the images themselves. One of these placeholders will contain the low-resolution preview image as well as a data attribute containing the path to the high resolution version.
Let’s call our low-resolution image placeholder .loadingImage and the high-resolution placeholder .overlay.
For this example we are working with the background style attribute as it is more commonly used with large hero images. This could easily be modified to work with an img tag as well.
Now for the CSS
As I stated above, we have 3 classes to account for. Our first class is the main container, and we will set it to position relative and overflow hidden. We are hiding the overflow because we are going to use CSS filter blur on our .loadingImage, and we don’t want to see it’s fuzzy perimeter.
Before setting up the image placeholder classes, we want to assign some shared parameters between them. We will set both inner div elements width, padding-top (see: Responsive Content Canvasing With Fixed Ratios), background-size, and background-position parameters.
You might notice we are using the !important flag here. Normally I would never do this, but in this example it serves as a means to not have to reassign those parameters when we pass the newly loaded high-res image into the .overlay placeholder.
Next set our .loadingImage class to have filter blur(5px). We do this because simply showing a low-resolution image does not look very appealing and almost defeats the purpose of this approach.
Now we need to setup the .overlay class. We set its position to absolute and top to zero to position it on top of our .loadingImage element. We are also going to set its opacity to zero and add a transition effect on the opacity to ease in at 200ms. This will give us that nice transition into the new high-res image on load complete.
.progressive-image { position: relative; overflow: hidden; } .progressive-image div { width: 100%; padding-top: 100%; background-size: cover!important; background-position: center bottom!important; } .progressive-image .loadingImage { filter: blur(5px); } .progressive-image .overlay { position: absolute; top: 0; opacity: 0; transition: opacity 200ms ease-in; }
Final touches
Now, we pull it all together with some JavaScript magic. We are going to use a little jQuery here, but this could easily be achieved with raw JS as well. And for the sake of going that extra mile, we are wrapping everything in a for loop in case we want to have multiple progressive loading images on a page.
First, we create a new Image() object and set our placeholder elements as parameters. For the new image object, we give it an onload handler to swap out our .overlay placeholder background-image once the high-res version has completely loaded. We also set opacity to 1 to finally show the image in a smooth manner. (Remember our .overlay opacity transition from earlier.)
To kick everything off, let’s set our new image object’s source with the .loadingImage data attribute content (path to our high resolution image).
$(function(){ $('.progressive-image').each(function(){ var image = new Image(); var previewImage = $(this).find('.loadingImage'); var newImage = $(this).find('.overlay'); image.onload = function(){ newImage.css('background-image', 'url(' + image.src + ')'); newImage.css('opacity', '1'); }; image.src = previewImage.data('image'); }); });
And that’s it. We now have progressively loading images. And with very little code, I might add. See this Codepen project for the finished product with multiple progressive loading images: http://codepen.io/philsanders/pen/VPYmYN