It's time to lazy-load offscreen iframes!

Addy Osmani
Addy Osmani

Browser Support

  • 77
  • 79
  • 121
  • 16.4

Lazy-loading of <iframe> elements defers offscreen iframes from being loaded until the user scrolls near them. This saves data, speeds up the loading of other parts of the page, and reduces memory usage.

As with lazy-loading for images, use the loading attribute to tell the browser you want to lazy-load an iframe.

<iframe src="https://example.com"
        loading="lazy"
        width="600"
        height="400"></iframe>

This demo of <iframe loading=lazy> shows lazy-loading video embeds:

Why lazy-load iframes?

Third-party embeds cover a wide range of use cases, from video players to social media posts to ads. This content is often not immediately visible in the user's viewport, but users still pay the cost of downloading data and costly JavaScript for each frame, even if they don't scroll to it.

Data-savings from using iframe lazy-loading for an iframe. Eager loading pulls in 3MB in this example, while lazy-loading does not pull in this code until the user scrolls closer to the iframe.
Eagerly loading offscreen iframes means users waste data by downloading elements they might never see.

Based on Chrome's research into automatically lazy-loading offscreen iframes for Data Saver users, lazy-loading iframes could lead to 2-3% median data savings, 1-2% First Contentful Paint reductions at the median, and 2% First Input Delay (FID) improvements at the 95th percentile.

Lazy-loading off-screen iframes can also improve your page's Largest Contentful Paint (LCP). Because iframes often need a significant amount of bandwidth to load all their subresources, lazy-loading offscreen iframes can reduce bandwidth contention on network-constrained devices, leaving more bandwidth to load resources that contribute to a page's LCP.

How does built-in lazy-loading for iframes work?

The loading attribute lets a browser defer loading offscreen iframes and images until users scroll near them. loading supports two values:

  • lazy: a good candidate for lazy-loading.
  • eager: not a good candidate for lazy-loading. Load right away.

Using the loading attribute on iframes works as follows:

<!-- Lazy-load the iframe -->
<iframe src="https://example.com"
        loading="lazy"
        width="600"
        height="400"></iframe>

<!-- Eagerly load the iframe -->
<iframe src="https://example.com"
        width="600"
        height="400"></iframe>

Not specifying the attribute has the same impact as explicitly eagerly loading the resource.

If you need to dynamically create iframes using JavaScript, setting iframe.loading = 'lazy' on the element is also supported:

var iframe = document.createElement('iframe');
iframe.src = 'https://example.com';
iframe.loading = 'lazy';
document.body.appendChild(iframe);

How does lazy-loading popular iframe embeds impact the user experience?

Making lazy-loading iframes the default would make websites much more responsive. The following examples show Time to Interactive (TTI) improvements and data savings for media embeds, but lazy-loading advertising iframes can give similar benefits.

YouTube

Lazy-loading YouTube video embeds saves around 500KB on initial page load:

<iframe src="https://www.youtube.com/embed/YJGCZCaIZkQ"
        loading="lazy"
        width="560"
        height="315"
        frameborder="0"
        allow="accelerometer; autoplay;
        encrypted-media; gyroscope;
        picture-in-picture"
        allowfullscreen></iframe>
Chrome.com achieved a 10 second reduction in Time To Interactive by lazy-loading offscreen iframes for their YouTube video embed
Chrome.com reduced its TTI by 10 seconds by lazy-loading offscreen YouTube embeds.

Instagram

Instagram embeds provide a block of markup and a script that injects an iframe into your page. Lazy-loading this iframe avoids having to load all the script the embed needs, and can save about 100 kB on initial load. Because these embeds are often displayed below the viewport in most articles, this is a reasonable candidate for iframe lazy-loading.

Spotify

Lazy-loading Spotify embeds can save 514 KB on initial load.

<iframe src="https://open.spotify.com/embed/album/1DFixLWuPkv3KT3TnV35m3"
        loading="lazy"
        width="300"
        height="380"
        frameborder="0"
        allowtransparency="true"
        allow="encrypted-media"></iframe>

Facebook's social plugins

Facebook social plugins let developers embed Facebook content in their web pages. The most popular of these is the Like plugin, a button that shows how many users have "liked" the page. By default, embedding the Like plugin in a web page using the Facebook JSSDK pulls in around 215 KB of resources, 197 KB of which is JavaScript. The plugin often appears at the end of an article or near the end of a page, so loading it eagerly when it's offscreen can be suboptimal.

Facebook Like Button
Facebook's Like plugin.

Thanks to engineer Stoyan Stefanov, all of Facebook's social plugins now support standardized iframe lazy-loading. Developers who opt into lazy-loading through the plugins' data-lazy configuration can now prevent these plugins loading until the user scrolls nearby. This lets the embed keep functioning for users that need it, while saving data for users who don't scroll all the way down a page. We are hopeful this is the first of many embeds to explore standardized iframe lazy-loading in production.

Cross-browser iframe lazy-loading

You can apply iframe lazy-loading to your site as a progressive enhancement. Browsers that support loading=lazy on iframes lazy-load the iframe, and browsers that don't support the loading attribute safely ignore it.

You can also lazy-load offscreen iframes using the lazysizes JavaScript library. You might want to do this if you:

  • Require more custom lazy-loading thresholds than standardized lazy-loading offers
  • Want to offer users a consistent iframe lazy-loading experience across browsers.
<script src="lazysizes.min.js" async></script>

<iframe frameborder="0"
      class="lazyload"
    allowfullscreen=""
    width="600"
    height="400"
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>

Use the following pattern to feature detect lazy-loading and fetch lazysizes when it's not available:

<iframe frameborder="0"
      class="lazyload"
    loading="lazy"
    allowfullscreen=""
    width="600"
    height="400"
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>

<script>
  if ('loading' in HTMLIFrameElement.prototype) {
    const iframes = document.querySelectorAll('iframe[loading="lazy"]');

    iframes.forEach(iframe => {
      iframe.src = iframe.dataset.src;
    });

  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js';
    document.body.appendChild(script);
  }

</script>

Are there exceptions to offscreen iframe lazy loading?

An early experiment with automatically lazy-loading iframes for Data Saver users in Chrome had an exception for hidden iframes, often used for communications or analytics. These were prevented from loading lazily, and always loaded to prevent breaking those features.

The loading attribute doesn't apply these heuristics, so the developer always gets to choose what gets lazy-loaded. The loading attribute should always be honored, subject to distance limits and other browser choices (such as printing).

Resources

For more lazy-loading ideas, see web.dev's image and video lazy-loading collection.

With thanks to Dom Farolino, Scott Little, Houssein Djirdeh, Simon Pieters, Kayce Basques, Joe Medley, and Stoyan Stefanov for their reviews.