Lazy-load iframes

Lazy-loading is well-known to decrease load times, improve the UX and boost search engine rankings. An often overlooked opportunity is lazy-loading iframes — learn how.
Published
Updated
Typical Read
5 minutes
Sponsored
Do you run a development agency, freelance developer or offer website services. Contact me today for information about advertising.
Find your next web developer job
jobs by Indeed

Lazy-loading resources like JS, CSS, and especially images it first nature for most devs. But did you know you could lazy-load iframes as well — natively? Lazy-load iframes easily, no tricks or hack, with the loading attribute.

Lazy-loading is a massive performance win for web pages. Frontend developers have been doing this for years with JavaScript, CSS, and image files.

An often overlooked lazy-load opportunity is iframes. They’re notorious for slowing down webpages. In this article, we’ll solve that by learning how to lazy-load iframes.

tl;dr

Add a loading="lazy" attribute to the iframe tag that you want to load on demand. The browser will load these when users scroll near the element:

<iframe src="https://benmarshall.me" loading="lazy" />

Don’t forget to make your iframes responsive. It’s more important now than ever before. There’s no longer the standard desktop, tablet or mobile screens sizes and why you need to ensure you site & iframes look good on all devices.

Why should you lazy-load iframes?

Lazy-loading iframes are just as important, if not more so, as lazy-loading JavaScript, CSS, and image resources. When lazy-loading isn’t enabled, users pay the cost of downloading data and low Google performance scores.

For instance, it’s no secret that youtube iframe embeds slow down your page load. If you’re not auto-playing the video, ask yourself why are you slowing down your initial page load when you don’t need to?

Based on Chrome’s research, automatically lazy-loading offscreen iframes could lead to 2-3% data savings, 1-2% first contentful paint reductions, and 2% first input delay improvements. When switching to lazy-loading YouTube embeds for Chrome.com, an average of 10 seconds can be saved until our pages could be interactive on mobile devices.

Lazy-loading iframes can also help your Google rank — Google gives preferential treatment to sites that load faster.

How to Lazy-load iframes

What is lazy-loading? Last-loading gives webpages a massive performance boost by yielding priority to other resources that the user may need first. It postpones loading of all lazy-loaded resources until they’re about to come into the browser’s viewport.

iframes have a loading attribute that allows a browser to defer offscreen iframes and images until users scroll near them. This attribute supports three values:

  • lazy: good candidate for lazy-loading
  • eager: not a good candidate for lazy-loading, loads right away
  • auto: the browser determines whether or not to lazily load

The full specification can be found in a pull request on GitHub.

auto is currently a non-standard value, but it the default in Chrome today. Chrome intends on bringing a proposal for this value to the standards table.

Scroll distance threshold

All iframes above the fold (being visible without scrolling) load normally, others are loaded when the user scrolls near them. The distance when elements begin to load is dynamic and depends on:

  • Connection type (e.g. 3g, 4g, unknown)
  • Whether Lite Mode is enabled in Chrome for Android

The distance is chosen so that the deferred content almost always finishes loading by the time it becomes visible. Currently, these values are hardcoded in Chromium’s source and can be overridden using command line arguments.

It may seem like a big issue of the native implementation but actually, it has one substantial advantage – it depends on the effective connection type of user’s device. It would require a lot of work to detect it correctly and we can assume that the values provided by authors of that feature are calculated correctly, so we don’t need to worry about it.

Note: Chrome 77 allows to experiment how different connection types are affecting distance threshold by setting network throttling in DevTools.

The onload event

Lazily loaded image and iframe element’s onload events are triggered – as you might expect – when data is completely loaded. So when the element is lazily loaded, onload fires as a user scrolls near it and the data is fetched.

Document’s onload event works a little bit differently. Traditionally, the event has been fired when all iframes were already loaded. With lazy loading, the document doesn’t wait for deferred, off-screen elements to be loaded before triggering the event.

Browser compatibility

The loading attribute is supported by most popular Chromium-powered browsers (Chrome, Edge, Opera) and Firefox. The implementation for WebKit (Safari) is in progresscaniuse.com has detailed information on cross-browser support. Browsers that do not support the loading attribute simply ignore it without side-effects.

Feature detection

Detecting if the user’s browser supports lazy-loading iframes is easy by checking the loading property defined in the prototypes of HTMLIFrameElement:

if ('loading' in HTMLIFrameElement.prototype) {
  // Native image lazy-loading is available
} else {
  // Use polyfill or a 3rd-party library
}

Native iframe lazy-loading can be applied as a progressive enhancement. Browsers which support loading=lazy on iframes will lazy-load the iframe, while the loading an attribute will be safely ignored in browsers that do not support it yet.

It is also possible to lazy-load offscreen iframes using the lazysizes JavaScript library. This may be desirable if you:

  • require more custom lazy-loading thresholds than what native lazy-loading currently offers
  • wish to offer users a consistent iframe lazy-loading experience across browsers

Check out the example below on how to lazy-load iframes for both legacy and modern browsers:

<iframe class="lazyload" data-src="https://benmarshall.me">
</iframe>
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);
}

loading attribute isn’t just for iframes

The loading attribute can be used for more than just iframes, it works for images too.

This single attribute to perform a complex but useful operation is the ideal solution for lazy loading just about anything. In Chrome 76 onwards, you can use the attribute to lazy-load images without the need to write custom lazy-loading code or use a separate JavaScript library.

Did you find Lazy-load iframes useful? Get articles in your inbox.

…and don’t worry, I hate spam as much as you. Expect to hear from me at most once a week.

Latest Job Postings
Posted on Aug 9, 2020 at 9:17pm
Full-time
Los Angeles
Posted on Aug 9, 2020 at 9:15pm
Full-time
Los Angeles
Posted on Aug 9, 2020 at 1:19am
Littleton, CO
jobs by Indeed
Sponsored
Help support open-source projects & pro-bono non-profit services by donating today.
Sponsored
Do you have a great article to share you want to contribute? Contact me about your idea.
Sponsored
Sponsor my site by donating to help support open-source projects, like WordPress Zero Spam, Referrer Analytics & others.
Sponsored
Sponsor my site by donating to help support open-source projects, like WordPress Zero Spam, Referrer Analytics & others.
Sponsored
Need help with website, a boost in ranking or online marketing? Contact me today for a free quote.

Leave a Reply

Your email address will not be published. Required fields are marked *

All comments posted on 'Lazy-load iframes' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.

You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.

Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.