Sequential Image Loading for Optimized Load Times

If you’re creating a page that is very image heavy, you probably want to make sure that the images further up the page take loading priority over the ones further down the page.

This is especially important for mobile sites where you don’t want a huge image at the bottom of your page taking precious bandwidth away from the more important images above the fold.

There are a lot of ways to accomplish this, but I think I have the easiest solution — sequential loading.

Let’s take some basic markup that we’ll want to make load sequentially:

<img src="https://lorempixel.com/400/200/animals/">
<img src="https://lorempixel.com/400/300/animals/">
<img src="https://lorempixel.com/500/400/animals/">
<img src="https://lorempixel.com/400/500/animals/">
<img src="https://lorempixel.com/400/600/animals/">

For sequential loading, we need to do three things:

  1. Make sure the images don’t load too soon
  2. Figure out which images need to be loaded
  3. Load them, in order, one after another

The first one is simple enough — if an image doesn’t have a source, it won’t load. But we also need a way to come back later and set the image source to the correct image. A “data” attribute would be a perfect fit here:

<img data-src="https://lorempixel.com/400/200/animals/">
<img data-src="https://lorempixel.com/400/300/animals/">
<img data-src="https://lorempixel.com/500/400/animals/">
<img data-src="https://lorempixel.com/400/500/animals/">
<img data-src="https://lorempixel.com/400/600/animals/">

Now that there’s no src on the images, they won’t load until we want them to. But how do we tell the browser what images to load, and when to do it?

For this part we’ll use the duct tape of the internet, jQuery. Our second objective is that we need to get all of the images we want to load, and with jQuery that’s easy:

// get all of the images
var images = $('img[data-src]');

// keep track of how many images we've loaded
var numImagesLoaded = 0;

Now that we know what images need to be loaded, and how many have already been loaded, we can get make a simple function to actually load them:

function preloadNextImage() {
    // if we've reched the end of our 'images' array, stop
    if(typeof images[numImagesLoaded] === 'undefined') {
        return;
    }
    // load the image into a jQuery object
    var $image = $(images[numImagesLoaded]);
    // set a listener on the image so that when it's
    // done loading, it will call this function recursively
    $image.on('load', function() {
      // after the image loads, increase the index
      // and then load the next one
      numImagesLoaded++;
      preloadNextImage();
    });
    // set the src on the image to what is in data-src
    $image.attr('src', $image.data('src'));
}

Now you can put it all together:

var numImagesLoaded = 0;

var images = $('img[data-src]');

preloadNextImage();

function preloadNextImage() {
    // if we've reched the end of our 'images' array, stop
    if(typeof images[numImagesLoaded] === 'undefined') {
        return;
    }
    // load the image into a jQuery object
    var $image = $(images[numImagesLoaded]);
    // set a listener on the image so that when it's
    // done loading, it will call this function recursively
    $image.on('load', function() {
      // after the image loads, increase the index
      // and then load the next one
      numImagesLoaded++;
      preloadNextImage();
    });
    // set the src on the image to what is in data-src
    $image.attr('src', $image.data('src'));
}

And there you have it, stupid simple sequential image loading.

View a demo here.

Leave a Reply

Your email address will not be published. Required fields are marked *