Optimizing page performance by lazy loading images

29 Apr 2021

I recently made some performance improvements to the DebugBear homepage. This article explains how to use the loading="lazy" HTML attribute to make your website render more quickly.

Page load timeline with and without image lazy loading

The problem: resource prioritization

The filmstrip above shows that the background image of the hero section only loads after about 1.6s. Before that a plain blue background is used.

Blue and image backgrounds

Why does it take so long? We can find out by looking at the detailed request waterfall.

The request for the background image is only made relatively late. Before that the browser loads several large below-the fold images, using up the available bandwidth.

Order page images are loaded in

The right-most part of each request shows the response body being downloaded. The darker areas show when data for that request is received, so you can see what requests the browser is spending bandwidth on.

Most of this is allocated to the below-the-fold images, but the browser is also loading some JavaScript code before loading the hero background image.

The solution: lazy loading images with the HTML loading attribute

By default, all images on a page are loaded as soon as the user opens the page. Setting the loading attribute to lazy can defer fetching images and iframes until the user scrolls near the element.

<img src="image.png" loading="lazy" />

The below-the-fold images are now deprioritized, and the browser loads the background image much earlier. The Largest Contentful Paint goes from 1.6s to 0.8s.

(The filmstrip makes it look like the above-the-fold image loads later than before, but this is only minor variation, not an effect of the lazy loading change.)

Rendering the homepage with and without lazy loading images

Native lazy loading is a relatively new browser feature, and currently only Chrome, Edge, and Firefox support it. Firefox doesn't support the loading attribute on iframes yet.

If a browser doesn't support the loading attribute the images will be downloaded as soon as the user opens the page.

loading attribute brower support table

What if my user loads an article and then wants to read it offline?

If you're writing a long blog post readers might prefer to load it on their phone and then read it when they don't have an internet connection.

When images are lazy loaded they'll be missing once the reader scrolls down the page. To avoid that you can remove the loading attribute from the img tags after the initial page load.

setTimeout(() => {
  document.querySelectorAll("img[loading='lazy']")
    .forEach(el => el.setAttribute("loading", ""))
}, 5000)

The images will then be downloaded right away, but without having affected the initial page load.

Images are loaded right away when loading attribute is removed

The trade-off here is bandwidth consumption: on a mobile plan with limited traffic users may prefer not loading images that they aren't going to see.

A worse Lighthouse Performance score

One thing that happened when I enabled image lazy loading and later removed the loading attribute is that my Lighthouse Performance score went down.

Charts showing LCP getting better and Performance and TTI going down

The initial render was a lot quicker, but Time to Interactive went up because more network activity was moved to later in the page load process, keeping the network active for longer.

Is this a problem? Not really. I care about user experience and the Core Web Vitals Google uses for search engine rankings. Time to Interactive doesn't matter in either case.

One easy workaround would be to increase the delay from 5s to 10s. Lighthouse assumes the network is idle after 5s of no activity, so pushing back the extra image requests will improve Time to Interactive.

Summary

You can use image lazy loading to prioritize more important requests and speed up the initial rendering of your page.

The Lighthouse Performance score isn't the most important metrics to optimize for, and sometimes it's ok to make a performance optimization that reduces the Performance score.

DebugBear is a website monitoring tool built for front-end teams. Track performance metrics and Lighthouse scores in CI and production. Learn more.

Get new articles on web performance by email.

DebugBear logo
Track and analyze site speed with DebugBear.
➔ Learn more