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://www.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-loadingeager
: not a good candidate for lazy-loading, loads right awayauto
: 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 progress. caniuse.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://www.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.
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.