What are deferred images?

  • A deferred image is downloaded after the initial page load
  • Images not initially visible on a page (below the fold) can be deferred allowing what is visible to load faster

Deferring images for faster pages

This article will describe a simple way to defer images without jQuery or lazy loading.

One of the main reasons a page loads slowly is images. There is not an internet user anywhere that has not seen an image, slowly loading from top to bottom.

Even as a user watches that image slowly loading, there are often multiple images further down the page that are not visible to that user yet, and they are all loading too.

All these images are competing for the same bandwidth as your page resources such as css and javascript. This means images are getting in the way of providing the initially visible part of your webpage to users as quickly as possible.

This is a well known issue

The main way developers and webmasters have solved this issue is through a method called lazy loading.

Lazing loading images is a solution where as a user scrolls down the page, images are loaded as needed. There are many wonderful things about lazy loading and I use it often, but it has some issues...

  • Lazy loading can cause performance issues.
  • Lazyloading does not provide a viable solution for some webpages.
  • Lazy loading is not ideal for mobile performance.

Deferring images without lazy loading or jQuery

The truth is that lazy loading images is just a more complicated way of deferring images.

To get back to basics we will be talking about deferring images without lazy loading. But let's first define the stuff that lazy loading is actually doing.

  1. Observing a scroll position
  2. Monitoring scroll position
  3. Reacting to a scroll position
  4. deferring images

In the four things above, only one of them is the deferring of images.

Let's discuss the deferring images part

When a webpage is rendered in a browser the browser will attempt to download all the images it can find on the page. If there are two images on the page, it will download two images. If there are one hundred images on the page it will download all one hundred.

This is default browser behavior. It has to request and download all images.

The only reliable way around this (for all browsers) is to trick the browser into thinking those images aren't there.

The way that is done in lazy loading and elsewhere is to provide a tiny default image in our html, and then switch that default image via javascript to the real image we want to display.

This means that images are marked up something like...

<img src="fake.png" data-src="real-image.png"

When the page is initially loaded, the browser will get the "fake image" once and then that will be the only image the browser sees, so whether you have one image or a hundred, it won't matter because the browser has already downloaded the fake image.

Then via javascript we swap out the fake image with the real one.

When the browser sees that there is a new image in the html, it will now download it.

This relatively simple step can provide amazing results. I recently made a page that took eight seconds to load go down to less than a second using only this method.(we will describe the method in full below with example code)

This is where we defer the images without lazy loading

In the scenario of a one page template, there is no reason to do all the things that lazy loading does (observe, monitor and react to a scroll postion).

Why not just defer those images and have them load immediately after the page has loaded?

How to do it

To do this we need to markup our images and add a small and extremely simple javascript. I will show the method I actually use for this site and others. It uses a base 64 image, but do not let that scare you.

The html

<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">

The javascript

<script>
   function init() {
       var imgDefer = document.getElementsByTagName('img');
       for (var i=0; i<imgDefer.length; i++) {
           if(imgDefer[i].getAttribute('data-src')) {
               imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
           }
       } 
   }
   window.onload = init;
</script>

Usage

For most pages you can simply put the script right before the end body tag in your html. As far as the images go you want to copy the code above (labeled "the html") and replace "your-image-here" with your actual image path.

  • image
  • deferred
  • page-speed