Chrome's Native Lazy Loading for Wordpress Images

Updated on November 26, 2019

What is Native Lazy-Loading?

When a browser opens a webpage, it normally loads every image on it—even ones far below the visible area, or viewport. Some visitors might not ever scroll further down the page, which means the bandwidth spent loading those unseen images is wasted.

In an ongoing quest for faster internet, developers came up with clever ways to defer the loading of images outside the viewport until the user scrolls near them. All of these solutions required JavaScript, though, which adds its own overhead and breaks images altogether for those who browse with JavaScript disabled.

The situation changed with the arrival of Chrome 76. From that version onward, Chrome and Chromium-derived browsers support native lazy-loading. All you have to do is add a single attribute to your image tags:

<img src="cutecat.jpg" loading="lazy" />

It's that simple. And if a different browser doesn't support the new attribute yet, the images will load normally, no harm done.

Now I'll tell you how to add these attributes to your images in Wordpress automatically (for the most part).

Native Lazyload Plugin

First off, Google's own Native Lazyload plugin can do all the work for you. At the time of writing, it's rife with one-star reviews claiming it broke their site, but I'm sure it will get fixed eventually. Even then, I won't use it because I'm a curmudgeon and avoid installing plugins as much as possible, but if you're looking for the fastest and easiest solution, this is it.

1. Add Lazy Loading Attribute to Featured Images and Attachments

Adding the loading="lazy" attribute to featured images (previously called post thumbnails), galleries, and images on attachment pages is easy by using the wp_get_attachment_image_attributes hook. Simply copy and paste the code below into your theme's functions.php file:

add_filter( 'wp_get_attachment_image_attributes', 'add_lazy_load', 10, 3 );
function add_lazy_load( $attr, $attachment, $size ) {
    if ( ! array_key_exists( 'loading', $attr ) ) {
        $attr['loading'] = 'lazy';
    }
    return $attr;
}

Kudos to akkis on Wordpress Code Reference for this snippet.

You can verify that this works by inspecting the source code of a featured image or an attachment page on your site:

2. Add Lazy Loading Attribute to New Images Inside Posts

The code above doesn't affect single images added via post editor. For that I've used the image_send_to_editor hook as shown below. Add it to functions.php like before.

add_filter( 'image_send_to_editor', 'lazyloading', 10, 8 );
function lazyloading( $html ) {
    $html = str_replace( ' />', ' loading="lazy" />', $html );
    return $html;
}

What this does is simply tack on the loading="lazy" attribute whenever inserting an image into a post via "Add media". When you switch to "Text" in Classic Editor or click the three dots and then "Edit as HTML" in Gutenberg, you'll see something along these lines:

As you might've guessed, this only affects newly inserted images. Galleries and post thumbnails aside, existing images in older posts won't receive the lazy loading treatment. There's a good reason for this: Images inserted into posts are essentially a part of that post, and can't be filtered directly.

You can, of course, write a function that searches the contents of an entire post and tacks on the lazy loading attribute to each <img> tag it finds, but that strikes me as inefficient. The process would have to be repeated each time a visitor views a post, putting undue load on your server and slowing your site, which is the opposite of what we're trying to do.

3. Lazy Loading for Existing Images in Posts

To deal with existing images in older Wordpress posts, I can't really think of anything smarter than doing a simple search & replace. (If you have a better idea, please share it in the comments!) This might not seem very elegant, and it hardcodes the loading="lazy" attribute into posts, but it only has to be done once.

To this end, I've used a plugin called Better Search Replace on my wp_posts table as follows:

Do be careful and make a database backup beforehand, because it can easily break things.
Do be careful and make a database backup beforehand, because it can easily break things.

If you're going to do this at all, it's best to do it before you modify the editor as described in Step 2, or you'll get image tags with duplicating attributes. Again, only do this once.

And if this attribute never gains mainstream support, you can always remove it from your posts by performing the search & replace in reverse.

4. Lazy Loading for Commenter Avatars

Comments are usually located at the bottom of the page, so user avatars are a good target for lazy loading. You could use this filter in your functions.php:

add_filter( 'get_avatar' , 'lazyavatar' , 1 , 1 );
function lazyavatar( $avatar ) {
	$avatar = str_replace('<img','<img loading="lazy"',$avatar);
    return $avatar;
}

Or, if your theme uses a custom comment callback, you might find the get_avatar() function and add loading="lazy" to it through the extra_attr parameter.

If you're using a more modern comment system like Disqus, this isn't necessary.

5. Lazy Loading Youtube Videos

One thing I haven't mentioned so far is that lazy loading can also be applied to iframes. When you paste a link to a video on Youtube (or other supported site), Wordpress automatically turns it into an iframe to embed it on your post. To make it load lazily, we can use the embed_oembed_html filter as follows:

function lazyoutube($html) {
	$html = str_replace( '<iframe', '<iframe loading="lazy"', $html );
    $html = '<div class="video-container">'.$html.'</div>';
    return $html;
}
add_filter( 'embed_oembed_html', 'lazyoutube', 10, 1 );

Verifying the Improvement

There are several ways to test if lazy loading works. The easiest is to open your website in the latest version of Chrome, fire up the Developer tools (Ctrl + Shift + I), and switch to the Network tab. Navigate to a long page with a lot of images and scroll down. You should see that the images at the far bottom won't load until you scroll lower.

Don't be alarmed if the images load immediately! The threshold at which Chrome will load an image depends on multiple factors, including connection speed. Anecdotally, the distance also appears significantly higher than JavaScript-based solutions, so you might want to find a really long page for testing.

An alternative way is to launch an Audit via the same developer tools, or use the web-based PageSpeed Insights test. Look for the "Defer offscreen images" message, which will show up in the "Opportunities" section if not yet implemented, and in the "Passed audits" section if lazy loading is working.

A green "Defer offscreen images" result in Google's PageSpeed Insights is what you want to see.
A green "Defer offscreen images" result in Google's PageSpeed Insights is what you want to see.

Now you've shaved a few milliseconds off your Wordpress site's load time. Good job!

Questions & Answers

    Comments

      0 of 8192 characters used
      Post Comment

      No comments yet.

      working

      This website uses cookies

      As a user in the EEA, your approval is needed on a few things. To provide a better website experience, turbofuture.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

      For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://turbofuture.com/privacy-policy#gdpr

      Show Details
      Necessary
      HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
      LoginThis is necessary to sign in to the HubPages Service.
      Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
      AkismetThis is used to detect comment spam. (Privacy Policy)
      HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
      HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
      Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
      CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
      Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
      Features
      Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
      Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
      Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
      Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
      Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
      VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
      PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
      Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
      MavenThis supports the Maven widget and search functionality. (Privacy Policy)
      Marketing
      Google AdSenseThis is an ad network. (Privacy Policy)
      Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
      Index ExchangeThis is an ad network. (Privacy Policy)
      SovrnThis is an ad network. (Privacy Policy)
      Facebook AdsThis is an ad network. (Privacy Policy)
      Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
      AppNexusThis is an ad network. (Privacy Policy)
      OpenxThis is an ad network. (Privacy Policy)
      Rubicon ProjectThis is an ad network. (Privacy Policy)
      TripleLiftThis is an ad network. (Privacy Policy)
      Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
      Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
      Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
      Statistics
      Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
      ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
      Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)
      ClickscoThis is a data management platform studying reader behavior (Privacy Policy)