Quick and Simple Lazy Loading for Responsive WordPress Sites

Recently I spent some time looking at the ‘waterfall’ of a website. This shows each asset that’s loaded, and how long it takes.

One thing that stood out: Images loaded in the sidebar.

samplesitewaterfall

This sample site loads lots of images in the sidebar, even while still trying to render the above-the-fold portion of the page.

The site I was working on had a left-handed sidebar, so all the images were loaded before the main content itself.

The outcome for the mobile layout was even worse: As in many responsive sites, the sidebar was not even displayed. This slowed performance even more, not to mention the extra data load for the mobile user.

Some sites will display the sidebar at the foot of the webpage on mobile layouts.

There doesn’t seem to be too much research on whether users on mobile devices ever scroll so far as to tap on other links well below the content. Of course the sidebar itself is another argument: Should we even have one?

Quick and Dirty Lazy Load

As the site is in WordPress, I looked around for some lazy loading plugins.

Lazy load typically refers to delaying the GET of the <img> until it appears in the viewport.

Of course there are myriad different techniques, but I found most of them had too many features, and I didn’t want yet another heavy script to add to the Javascript load. I don’t need a full-fledged lazy loader. I just want to delay certain images UNTIL the document is ready.

Step 1: Change the image markup

We need to put in a default blank image, and put the actual image source in a new attribute.

Advertisement

Before

<img src="myimage.jpg" />

After

<img data-src="myimage.jpg" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />

Rather than an extra HTTP GET to call in a tiny 1×1 pixel image, I’ve settled for a tiny base64-encoded 1×1 transparent GIF.

Step 2: Add some Javascript to load the images

As this site already uses jQuery, just a few lines of code are needed.

docWidth = window.innerWidth || (document.body ? document.body.offsetWidth : 0);
if (docWidth > 599) {
   $(".sidebar").find("img[data-src]").each(function () {
         var src = $(this).attr("data-src");
         $(this).attr("src", src).removeAttr("data-src");
   });
}

This code is placed inside $(document).ready(function(){...} function, so will not execute until… well… the document is loaded. This means these images load last.

The code looks for each image with a data-src attribute in the sidebar, and sets the src to the correct filename. This prompts the browser to go and get all the images.

We only do this where the viewport is 600px or more (this equates to our media queries), so mobiles will not load these images at all.

That’s it!

What does this look like in WordPress?

Here’s some code I added to one of my functions inside the functions.php.

It is part of a “recent posts” type function that shows a post thumbnail. We pull out the thumbnail URL and build the  img element ourselves.

<?php 
if (has_post_thumbnail()) { 
    $src = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ));
    $defimg = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
?>   
   <a href="<?php echo get_permalink($post->ID) ?>"><?php printf( '<img src="%s" data-src="%s" class="attachment-cat-thumb" width="85"/>', $defimg, esc_url( $src[0] )); ?> </a>
<?php } ?>

This will output the markup we need to drive our very lazy loader.

The outcome of all this was preventing a load of up to 100kb of images being sent down a mobile connection that won’t even be displayed! And, could have potentially had a blocking effect on the main content render.

On a fast connection this won’t mean much, but on slower high-latency 3G connections, this is a meaningful difference.

Hi, I'm James, and for the last decade I've made a living by making my own blogs and websites.
Updated: September 14, 2016

Add a Comment