Lazy Loading Images

Images are generally the heaviest assets on a webpage- so if you’re interested in fast load times for users, this is one of the best places to optimize.

Lazy Load Your Images

One popular technique for speeding up the initial load time is called “lazy loading”. It works by replacing the source of images (src=”/example.gif”) with a transparent placeholder image (src=”/pixel.gif”). This allows everything else on the page (text,fonts,scripts,etc) to render first.

The original source for the image is generally saved into a data attribute, such as “data-src”, so it can be accessed in later.

This is helpful because we now have complete control over when images get loaded. At any time the source of the image (src=”/transparent.gif”) can be replaced by the actual source in the data attribute. (See a simple jQuery plugin example).

Several lazy load scripts also work by only loading in the actual images once they enter the viewport, which means the images in the footer won’t load in until the user has actually scrolled down that far. This can save bandwidth for the user as images that don’t get viewed, won’t get loaded.

Also, many jQuery plugins use a quick fadeIn function when replacing images with their actual source, which can be a nice visual effect.

Lazy Loading in WordPress

The key in WordPress is to filter the_content, post_thumbnail_html, and get_avatar content so that any images will have their source replaced by the transparent placeholder.

The best solution I found for this is in the Lazy Load plugin code by Automattic, Jake Goldman, 10Up, and Mohammad Jangda. If you’re simply looking for the easiest way to lazy load images on your site I highly recommend using the plugin.

The Lazy Load plugin uses a single function to filter any $content passed to it, and replace any images within that $content with the placeholder image. Here’s what it looks like (slightly modifed):

function add_image_placeholders( $content ) {
	// Don't lazyload for feeds, previews, mobile
	if( is_feed() || is_preview() || ( function_exists( 'is_mobile' ) && is_mobile() ) )
		return $content;

	// Don't lazy-load if the content has already been run through previously
	if ( false !== strpos( $content, 'data-src' ) )
		return $content;

	// In case you want to change the placeholder image
	$placeholder_image = apply_filters( 'lazyload_images_placeholder_image', get_template_directory_uri() . '/images/pixel.gif' );

	// This is a pretty simple regex, but it works
	$content = preg_replace( '#<img([^>]+?)src=[\'"]?([^\'"\s>]+)[\'"]?([^>]*)>#', sprintf( '<img${1}src="%s" data-src="${2}"${3}><noscript><img${1}src="${2}"${3}></noscript>', $placeholder_image ), $content );

	return $content;
}

Then, you can add your filters to replace images in specific bits of content.

Post Content:

add_filter( 'the_content', 'add_image_placeholders', 99 );

Featured Images:

add_filter( 'post_thumbnail_html', 'add_image_placeholders', 11 );

Avatars (generally in comments):

add_filter( 'get_avatar', 'add_image_placeholders', 11 );

Javascript

Once you’ve implemented the code above in your theme, you shouldn’t be seeing any images in the content that you filtered- just the placeholder pixel.

So, now you can replace the images when you choose with a bit of jQuery:

jQuery('img').attr('src',jQuery(this).attr('data-src'));

The Lazy Load WordPress plugin uses jQuery Sonar, which doesn’t replace images until it is in the viewport window.

There are also a ton of other scripts that do something similar. I say find one that works for you (it’ll likely need a bit of customization), or roll your own.

Should you lazy load images in a theme?

I originally had a homebrewed version for lazy loading thumbnails in my Visual theme, but have since decided to remove it.

I think functionality like this is much better handled by a plugin like Lazy Load. I plan to start encouraging users to install this plugin, and may even add a notice and automatic loader for it.

About Devin

I am a developer based in Austin, Texas. I run a little theme shop called DevPress and help manage a WooCommerce shop with Universal Yums. Find me on twitter @devinsays.

11 Responses

  1. But how does the google bot interpret the tags? As far as it knows, you only have 1 image, which is the transparent pixel. I think you should reserve this to when you are generating content in JS (e.g. an infinite scroll) and have a fallback for bots.

  2. The solution (lazy loading images) or “you-don’t-see-i-don’t-give” is great but it is a pity that it has an issue with Google’s image search. It is important for my sites since a lot of the traffic is coming via image searches.

  3. Hi Devin & Co.

    I took a while to find solutions to this method, especially in regard to Google.

    The problem is I’m not engineer WordPress. But I can think of a solution.

    I’ve been studying the method Adapative Images (adaptive-images.com), and combined with your method might work.

    I mean, using a system similar to adaptative images (or any php) could generate a copy with ridiculous picture quality (eg 10% quality).

    Later upgrade the quality of the image with jquery & data-src.

    This way Google will not be angry with us. I imagine that would interpret lazy load method as offensive as it feeds on our images.

    On the other hand, in the case of Spain (I’m from there). Currently Google Images brings no traffic. This may be different in U.S.

    With this combination of methods I think we will not lose a single spot in the rankings.

    I gave my point of view with the role of photographer. One of my skills.

    And I’ll keep this post & your blog because I’m looking for a similar solution.

    Please excuse my English & have fun!

  4. chris

    devin. i use adaptive images. when u say it uses double bandwidth is this compared to lazy loading the images or did u mean something else? half of my job is seo and half is creating brochure websites so any new practices i do in the web design / frount end is always influenced by what google will think. i think Sebastián was on to something….

  5. Petar

    I’m trying to follow your instructions in order to get the images on my website to slowly fade in as they become visible, but not being really good at PHP/Wordpress I am having some trouble.

    What I’ve done is install the lazyload plugin that you mentioned, and I also added those filters to my functions.php file.

    The result is that the following error is popping up on my page:

    Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, ‘add_image_placeholders’ was given in /home3/petar123/public_html/XXXXX.com/wp-includes/plugin.php on line 173

    I barely understand what I am trying to do here, so any explanation would be greatly appreciated.

    Regards,

    Petar

  6. Ben

    Hi Devin
    Thanks for the snippet, very handy and been using it :) but just realize something and cant find answers anywhere about lazy loading. I’m wondering if it’s actually the same as using some viewport-detect plugin? And what about dessandro’s ImagesLoaded?

    Just happen to be working on something that’s gonna be using masonry so obviously will need imagesloaded. All working ok but somehow got this thought that its kinda not making sense anymore? Do we still to do lazy load when we use imagesloaded? And what about those in-viewport plugins?

    Hope could get your advice on this.

    Thanks!
    Ben

Leave a Reply to Devin Cancel reply