Lazy Loading Images: A Detailed Guide

“Lazy loading” is a technique for deferred content loading that optimizes page load speed. Images and other resources are loaded only when they approach the user's viewport.

So, what does this technique help with exactly?

Overall, this method enhances user experience, especially on mobile devices or with slow connections.

In this detailed guide on lazy loading, you will learn how to implement this technique, measure its impact, and the speed improvements observed post-implementation.

The Loading Attribute on IMG Tag

HTML provides the loading attribute, which allows you to specify how elements load. Add this attribute simply to the <img> tag.

<img src="image.webp" loading="lazy" alt="" width="200" height="200" />

The loading attribute can have two applicable values:

  • lazy – images load only when they are near or inside the viewport.
  • eager – images load immediately. This is the default setting.

How to Implement Lazy Loading for Images

Generally, we recommend a conservative approach, applying loading="lazy" to all images that are reliably outside the first visible part of the screen. However, there are several approaches, and we’ll explore them together.

Conservative Approach: Images Outside the First Viewport

Load all images outside the first viewport lazily using the loading="lazy" attribute. This is suitable for most situations.

Apart from the LCP element, we also recommend prioritizing images that form vital parts of the user interface or help users recognize the brand and clearly identify the website. Use the loading="eager" attribute for the LCP element, icons in the header (especially in the mobile header), and brand logo.

Radical Approach: All Images Except the LCP Element

If you are among the more experienced developers, you might apply lazy loading to all images except the largest image in the first viewport (the so-called LCP element).

Achieve this by making an exception for the LCP element, where you set loading="eager" or omit the parameter altogether.

All other images on the page will thus have loading="lazy". We caution that this solution is risky due to possible errors if, for example, the HTML code or website design changes.

A lazily loaded image must always have defined dimensions using width and height attributes. This prevents potential issues with the CLS metric. We also recommend always using the WebP image format.

Beware, Never Lazily Load the LCP Element!

Never use the loading="lazy" attribute on the LCP element, as it will worsen the LCP metric. The loading="lazy" attribute gives the element lower priority and delays its loading.

The worst combination is using a JavaScript lazy load and applying it to the LCP element, which some JavaScript libraries do automatically. First, you wait for the JavaScript to download and process, and only then does the browser download the image resource.

JavaScript Lazy Load

For more advanced implementation, JavaScript and the Intersection Observer API can be used.

The Intersection Observer API is a JavaScript API that allows you to observe elements as they approach the viewport. This can be used for custom lazy loading implementations.

However, this is a very advanced method and is certainly not recommended for regular optimization.

Benefits:

  • Flexibility.
  • Ability to define more complex loading conditions.
  • This type of lazy load can be used in JavaScript components like carousels and the like.

Drawbacks:

  • Higher complexity.
  • Waiting for JavaScript code to download and initialize.
  • Need for an alternative solution using <noscript> for browsers with JavaScript disabled.
  • Inability to fully utilize the browser's preload scanner.
  • If implemented incorrectly, images might not be visible to search bots.

Extended content management systems like WordPress or Drupal often offer plugins that implement lazy loading via JavaScript. If you use such a plugin, we recommend deactivating it and instead using native lazy loading with the loading="lazy" attribute.

Learn more about WordPress optimization in the article WordPress Optimization.

What Do We Recommend?

  • Use native lazy loading, which is widely supported.
  • Use JavaScript lazy loading only for more complex cases that cannot be covered by the native attribute.

Relationship Between the Loading Attribute and Load Priority Increase via Fetchpriority

The eager value instructs immediate image loading, without delay, even if the image is off-screen. The image loads just as fast as one without the loading attribute.

If you want to increase the loading priority of an important image (like an LCP image), use priority hints and the fetchpriority="high" attribute.

An image with loading="lazy" and fetchpriority="high" attributes does not load until it's off-screen. If it's inside or near the viewport, it's loaded with high priority. This combination is not necessary since the browser would likely load this image with high priority anyway.

Distance from Viewport: Image Loading Thresholds

All images immediately visible in the viewport without scrolling load instantly. Images far below the device's viewport load only when the user approaches them.

Chrome's lazy loading implementation aims to ensure off-screen images load early enough to complete by the time the user reaches them, loading them much sooner than they become visible in the viewport.

How is this set in Chrome? For fast connections (4G and above), Chrome has a distance threshold of 1250 px, and for slower connections (3G or lower), it has a threshold of 2500 px.

The final decision on when an image starts downloading is purely up to the browser, and the stated values are only indicative.

How to Analyze if Lazy Loading Is Implemented Correctly?

When implementing lazy loading, you need to determine which elements are suitable for lazy loading. It's also good to know how to verify if you've implemented lazy loading correctly.

Lazy Loading Analysis in Browser Timeline

Lazy loading can be analyzed using Chrome Developer Tools in the Performance section. Image loading is visible as separate requests over time as the user scrolls.

In the initial page view, only images visible in the first viewport or very close to it are downloaded.

Other images with the loading="lazy" parameter start downloading only upon user interaction, such as scrolling.

Lazy Loading Images with loading="lazy" start downloading only upon user interaction

Analysis in Lighthouse or Monitoringu PLUS by PageSpeed.ONE

In Lighthouse or Monitoringu PLUS, images suitable for lazy loading can be identified in the “Test Run Detail”. Images are listed under the warning “Defer offscreen images” in the Lighthouse synthetic test.

  1. In the main menu, select the “Opportunities” tab. Lighthouse Monitoring PLUS, Lighthouse test

  2. Select the test for a specific URL. Lighthouse Monitoring PLUS, Lighthouse test

  3. Find the item “Defer offscreen images.” Here, images suitable for lazy loading are listed. Lighthouse Images suitable for lazy loading are listed here.

The advice you receive in this section is quality and roughly corresponds to what we write above about a conservative approach to lazy loading.

Lazy loading can also be applied to other web elements besides images.

Lazy Loading for Iframes

Lazy loading can also be used on iframes, significantly improving Core Web Vitals metrics, for example, on pages with embedded videos or maps. The usage is quite similar to images:

<iframe src="https://example.com" loading="lazy"></iframe>

Lazy Loading Support in Browsers

All modern browsers support the loading attribute. We always recommend using native lazy loading over a JavaScript solution.

Examples from Our Practice in Speed Optimization

Implementing Lazy Loading on Images

For this client, using lazy loading on images in the main menu and footer led to a significant reduction in image data volume.

Reducing Image Data Volume Monitoring PLUS - reducing image data volume.

Figures in the image:

  1. Reduction in image data volume using lazy loading

The result was also an improvement in the LCP metric.

Replacing JavaScript Lazy Loading with Native Solution

Replacing JavaScript lazy loading with native lazy loading and increasing priority with fetchpriority="high" makes the LCP image download very early, significantly improving the LCP metric. In this case, the LCP metric sped up by about 2 seconds on a slow connection (Fast 3G).

Original State Original State

Explanations for the image:

  1. Start of LCP image download only after processing JavaScript app.js.
  2. Display of the LCP image on the page.

State After Optimization State After Optimization

Explanations for the image:

  1. Start of LCP image download occurs right after the HTML document download.
  2. Display of the LCP image on the page.

Summary

We recommend lazy loading images as one of the fundamental and highly effective methods for optimizing page load speed. Conservatively defer loading all images outside the first viewport. Be cautious when applying lazy loading to images that are the LCP element, as this can actually worsen speed.