When there is alot of data to load on the page, for example a page full of images, each image will download the image in chunks, making the user interaction a little choppy. One trick to fix this is to have the image instead use a placeholder image (spinner.gif), and only when the real image is completely downloaded replace the spinner for the real image.

Initial files:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>show spinner.gif until image is loaded!</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <div class="container">
    <h1>images to load</h1>

    <ul class="images">
      <li class="image">
        <img src="http://goo.gl/OOOxeF" data-imgsrc="url" />
      </li>
      <li class="image">
        <img src="http://goo.gl/OOOxeF" data-imgsrc="url" />
      </li>
      <li class="image">
        <img src="http://goo.gl/OOOxeF" data-imgsrc="url" />
      </li>
      <li class="image">
        <img src="http://goo.gl/OOOxeF" data-imgsrc="url" />
      </li>
    </ul>

  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script src="app.js"></script>

</body>
</html>

app.js

$(function() {

  // actual <img /> element is within div.image
  var imgs = $('.image img')

  console.log(imgs.length)

})

style.css

/*
===== General styles
 */

img {
  max-width: 100%;
}

/*
===== Custom styles
 */

.container {
  width: 840px;
  margin: 0 auto;
}

.images {
  list-style: none;
  padding: 0;
}

.image {
  width: 400px;
  float: left;
  padding: 10px;
}

we also have a spinner.gif file in our directory

Right now we are just rendering 4 images of our boy Harambe(rip). Instead of loading the image’s src directly, we are going to replace each image’s src with spinner.gif, and place the actual link to Harambe in <img src="spinner.gif" data-imgsrc="<harambelink.png"> />

index.html

<!-- ... -->

<ul class="images">
  <li class="image">
    <img src="spinner.gif" data-imgsrc="http://goo.gl/OOOxeF" />
  </li>
  <li class="image">
    <img src="spinner.gif" data-imgsrc="http://goo.gl/OOOxeF" />
  </li>
  <li class="image">
    <img src="spinner.gif" data-imgsrc="http://goo.gl/OOOxeF" />
  </li>
  <li class="image">
    <img src="spinner.gif" data-imgsrc="http://goo.gl/OOOxeF" />
  </li>

  <!-- copy and paste a few more so the interation will be more obvious (the images can load fast) -->

</ul>

<!-- ... -->

Now we should have a collection of spinner.gif’s going off. Now we are going to write the jQuery script to replace each image’s spinner.gif with the actual url, only once the image has been completely loaded on the page.

app.js

$(function() {

  var $imgs = $('.image img') // array of all images

  // iterate over each image
  $.each($imgs, function(i) {
    var oldImage = $($imgs[i])
    var newImage = $(new Image()) // create new image (not shown on DOM)
    newImage.attr('src', oldImage.data('imgsrc')) // with the src="<real_image_url>"

    // call .one() on each new image
    // (similar to .on() but only runs once)
    newImage.one('load', function() {
      // once the newImage w/ the real_image_src is loaded,
      // swap the old imgs src to real_img_src
      oldImage.attr('src', oldImage.data('imgsrc'))
    })
  })

})

We are iterating over each image we have and creating a new image (isn’t in the DOM) whose src=”real_img_url”. We attach an event handle onto each new image using .one(), which calls it’s callback function once the element has finished loading (probably best practice to keep the least amount of event handlers going at once). Once the new image has successfully loaded, we replace the src=”spinner.gif” with real_img_url, since it has successfully loaded on the page.

Final Result

See the Pen by matt (@matt) on CodePen.