Lazy Loading Images in Wordpress

The speed of your website is very important.  Even a minor difference in page speed (either a second or two faster OR slower) dramatically changes whether a user will stay on your website.

As web developers we need to build a website with page speed in mind from the start; not try and make changes after the website has been completed to decrease the load time.  There are plenty of things you can do to speed up your website.  One thing that we'll dive into today is called lazy loading.  If your website has a lot of images, the user will be downloading them all before they even see them.  This can increase the page speed significantly depending on how many images are on the page.  Lazy loading delays the loading of images until the user scrolls to them, which can help make your website load faster.

I'm going to walk you through how to enable lazy loading images in your Wordpress theme with a few simple functions!

The jQuery Scripts

The lazy loading script we'll be using today is the Lazy Load Plugin for jQuery by Mike Tuupola.  Download the minified version and copy it into your theme (mine will be in the assets/js folder of my theme).

Next, either create a new file to add the following snippet, or include it in your main Javascript file.  For this post I'll create a new script called lazyload.js:

$(function() {
  $("img.lazy").lazyload({ 
    effect : "fadeIn" 
  });
});

See the documentation for this plugin for additional parameters.

Enqueue Lazy Loading Scripts

Next, we need to enqueue the scripts, or include them in our theme.  I always have a function called <themename>_scripts where I enqueue all scripts and stylesheets.

add_action( 'wp_enqueue_scripts', 'themename_scripts', 100 );
/**
 * Enqueue our scripts and styles
 */
function themename_scripts() {
  // Our other scripts/styles will be here too...

  // Enqueue our lazy loading script
  wp_enqueue_script( 'themename-jquery-lazyload', get_stylesheet_directory_uri() . '/assets/js/jquery.lazyload.min.js', array('jquery'), null, true );
  wp_enqueue_script( 'themename-lazyload', get_stylesheet_directory_uri() . '/assets/js/lazyload.js', array('themename-jquery-lazyload'), null, true );
}

Modifying All Image Tags

We don't need to add the required attributes to each image manually. With a fairly simple function, we can modify any image tags within the post and page content so they are all lazy loaded.  The first thing we're going to do is create a helper function that modifies all <img> tags within a string by:

  • Adding the class lazy to the tag
  • Removing the src attribute
  • Adding a new attribute data-original and setting it's value to the original image source

Add the following function to your functions.php file:


/**
 * Takes a string and modifies any <img> tags within it by:
 * - Adding the class 'lazy'
 * - Removing the 'src' attribute
 * - Adding the 'data-original' attribute using the original 'src' value
 *
 * @param $content
 * @return string
 */
function themename_lazyload_modify_img_tags( $content ) {
  $content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");

  // Get out if we don't have any content
  if ( empty($content) )
    return $content;

  $document = new DOMDocument();
  libxml_use_internal_errors(true);
  $document->loadHTML(utf8_decode($content));

  // Grab all image tags
  $imgs = $document->getElementsByTagName('img');

  // Loop through all image tags
  foreach ($imgs as $img) {

    $existing_class = $img->getAttribute('class');  // Store existing class (if the image has one applied)
    $src = $img->getAttribute('src');               // Store src attribute value

    // Add 'lazy' class and the existing class(es) to the image
    $img->setAttribute('class', "lazy $existing_class");

    // Add a 'data-original' attribute with our 'src' attribute value
    $img->setAttribute('data-original', $src);

    // Remove our src attribute
    $img->removeAttribute('src');

  }

  $html = $document->saveHTML();
  return $html;
}

Lazy Loading Images Within Post and Page Content

Now that we have our helper function, we need to utilize it!  We are going to add a filter on the_content to modify any images inserted via the WYSIWYG editor.  Add the following function into your functions.php file:


add_filter( 'the_content', 'themename_enable_lazy_loading_the_content' );
/**
 * Modifies the content to enable lazy loading for all <img> tags
 *
 * @uses themename_lazyload_modify_img_tags()
 * @param $content
 * @return string
 */
function themename_enable_lazy_loading_the_content( $content ) {
  return themename_lazyload_modify_img_tags($content);
}

Now, any images you include in the WYSIWYG editor will be automatically lazy loaded!

What About Post Thumbnails?

Our previous function doesn't cover images uploaded as the featured image.  Fortunately there's a filter for that as well!  We'll add another filter on post_thumbnail_html. This function is basically the same as the function above, except we are going to pass the $html variable to our themename_post_thumbnail_html function.  Add this function to your functions.php file as well:


add_filter( 'post_thumbnail_html', 'themename_post_thumbnail_html', 10, 3 );
/**
 * Modifies the post thumbnail html to enable lazy loading for the image
 *
 * @uses themename_lazyload_modify_img_tags()
 * @param $html
 * @param $post_id
 * @param $post_image_id  
 * @return string
 */
function themename_post_thumbnail_html( $html, $post_id, $post_image_id ) {
  return themename_lazyload_modify_img_tags($html);
}

Voila! Now all post thumbnails will be lazy loaded as well.

Conclusion

Lazy loading is just one technique that will help your website load as quickly as possible.  There are still many other things to consider, such as having a reliable host, compressing your images and minifying your scripts, and much more.  Make sure lazy loading isn't the only technique you are using!

Feel free to comment and share any tips or techniques you use to keep your website loading quickly!

UPDATE: Images Loaded via AJAX

I recently came across a situation where images were being loaded via AJAX, and they weren't loading correctly. If you're using AJAX to load images and find yourself in the same situation, add the following to your JS file:


$(document).ajaxStop(function(){
  $('.lazy').lazyload({
    effect: 'fadeIn'
  }).removeClass('lazy');
});

Comments

Great tutorial.
Unfortunately, now none of your images will be indexed by Google. Which means by choosing to lazy load we miss out any SE traffic from image searches.

The content of this field is kept private and will not be shown publicly.