Lazy-loading
iframes.
A single attribute — loading="lazy"— tells the browser to defer off-screen iframes until the user is about to scroll near them. On a page with a YouTube embed below the fold, that one attribute can shave seconds off your LCP. Here is what it does, where it pays off, where it doesn't, and how to pair it with fetchpriority for the maximum Core Web Vitals win.
What loading="lazy" actually does
When the browser parses an iframe with loading="lazy", it does not immediately start fetching the iframe's src. Instead it records the iframe's position and reserves the layout box, then waits until the iframe is within a viewport-distance threshold of becoming visible.
Once the threshold is crossed, the browser fires the request, the document loads, the iframe paints — and from then on it behaves identically to an eager iframe. The user almost never notices, because the threshold is generous: Chrome currently uses about 1250 pixels below the fold on desktop and 1500 on mobile, so most lazy iframes finish loading well before the user scrolls them into view.
<iframe
src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
title="Demo"
loading="lazy"
allowfullscreen
></iframe>Browser support and behaviour
Implemented in every major browser since 2022 — Chrome 77+, Firefox 121+ (initially behind a flag, on by default since 2024), Safari 16.4+, Edge 79+. Total effective coverage is 96%+ globally as of 2026. Older browsers ignore the attribute and load the iframe eagerly, which is the correct fallback.
You can feature-detect support if you ever need to:
const supported = 'loading' in HTMLIFrameElement.prototype;Impact on Core Web Vitals
Three metrics are directly affected:
- LCP (Largest Contentful Paint).If your LCP element is above the fold and is competing for bandwidth with a heavy below-the-fold iframe, lazy-loading that iframe frees up the network and main thread for the LCP image or text. Real pages with a single below-the-fold YouTube embed routinely see LCP drop by 500–2000 ms.
- INP (Interaction to Next Paint). An iframe that loads while the user is trying to click something runs scripts on the main thread, which delays the next paint. Deferring the iframe until the user is far away from any critical interaction lowers contention dramatically.
- CLS (Cumulative Layout Shift). Lazy-loading does notfix layout shift on its own — if you do not reserve the iframe's height up front, the appearing iframe will still push content. Always set
widthandheight(or a sized CSS container) alongside lazy-loading.
<iframe
src="..."
loading="lazy"
width="560"
height="315"
style="aspect-ratio: 16 / 9; max-width: 100%; height: auto;"
></iframe>When NOT to lazy-load
- Above-the-fold iframes. If the iframe is the LCP element, you want it to load first, not last. Use
loading="eager"and considerfetchpriority="high". - Critical-interaction frames. Payment iframes, OAuth windows, consent banners — anything the user might need to interact with within seconds of page load. Lazy here is a footgun.
- Frames that drive other scripts. If a frame must finish loading before another piece of your code can run, deferring it just delays the dependent code. Order matters here, not bandwidth.
Pairing with fetchpriority
fetchpriority is a separate hint that tells the browser how important the resource is, independent of when it starts fetching. The pairing matters:
<!-- Below-the-fold video — lazy, normal priority -->
<iframe src="..." loading="lazy"></iframe>
<!-- Analytics / tracking — lazy AND deprioritise -->
<iframe src="..." loading="lazy" fetchpriority="low"></iframe>
<!-- Above-the-fold hero embed — eager AND prioritise -->
<iframe src="..." loading="eager" fetchpriority="high"></iframe>fetchpriority="low" on tracking iframes is a free win: the browser still loads them, but only after every higher-priority resource is queued.
Measuring the win
Three tools, in order of how seriously you should take them:
- Real-user RUM (Web Vitals JS library, CrUX dataset, or a vendor like SpeedCurve). The only honest measurement — synthetic tests cannot model real user bandwidth and device variation.
- Lighthousein Chrome DevTools. Useful for spotting offenders (“Defer offscreen iframes” audit). The numbers are synthetic; trust the direction, not the magnitude.
- WebPageTest with a connection profile that matches your audience. Best for before/after comparisons of specific changes.
Knowing which iframes you have
The first step before lazy-loading anything is to know what iframes are on each page. Most production pages have more than the developer remembers — chat widgets, consent banners, analytics, A/B tooling, ads. Use the Iframe Detector Chrome extension to list them in one click, sorted by visibility — the hidden ones are usually the first to lazy-load.
Frequently asked questions
Almost. The browser triggers the load when the iframe is within a heuristic distance of the viewport — Chrome currently uses ~1250px below the fold on desktop and ~1500px on mobile. So the iframe is usually fully painted before the user actually scrolls it into view, which is the desired behaviour.
No. Prerendering and prefetch happen at the navigation layer, before the iframe element exists. loading="lazy" affects when a present iframe starts fetching its src — it does not interact with preload directives at all.
Yes. loading="lazy" is an attribute on the iframe element itself, not on the embedded content. Any iframe can be lazy regardless of who provided the embed code. For YouTube specifically, also consider replacing the live player iframe with a lite-youtube-embed component for an even bigger win.
The mechanism is the same — browser-native intersection-based deferral — but iframes are usually heavier (full HTML documents, often with their own subresources), so the benefit per element is much larger. The threshold distances and behaviour are the same.
Yes, almost always. Tracking pixels and analytics beacons are not user-visible and rarely need to load before paint. Mark them loading="lazy" and fetchpriority="low" so they wait in line behind LCP-relevant resources.