Mastering Native Lazy Loading: When to Use loading="lazy" for <img> and <iframe>
Learn how to implement loading="lazy" on <img> and <iframe>, its impact on LCP, browser behavior, and how to keep CLS low. Get a concrete example and practical checklist.
29 Jul 2026, 04:26 UTC

The Problem: Why Lazy Loading Matters
When a visitor lands on a page, the browser starts fetching every resource it sees in the markup. Heavy images, embedded maps, or video iframes can dominate the initial payload, delaying the first paint and inflating the Largest Contentful Paint (LCP) metric. Modern browsers now expose a simple hint – loading="lazy" – that tells the engine to postpone fetching until the element is close to the viewport. This built‑in optimization removes the need for heavy Intersection Observer scripts for the common case.
How Native Lazy Loading Works
When the parser encounters <img loading="lazy"…> or <iframe loading="lazy"…>, the browser internally tracks the element’s distance from the viewport. The exact threshold is not exposed to developers; it depends on the browser’s heuristics, connection speed, and device capabilities. Once the element is within a few hundred pixels of the viewport, the browser initiates the request.
Key points:
- It is a hint. The browser may still load eagerly if it deems it necessary.
- All modern evergreen browsers support the attribute. Legacy browsers fall back to eager loading.
- JavaScript‑inserted elements are treated the same way, but some browsers may fetch them earlier.
Practical Implementation
Below is a minimal example that demonstrates lazy loading for both images and iframes. Notice the explicit width and height attributes – they reserve space and prevent layout shifts.
<!-- Hero image (always eager) -->
<img src="hero.jpg" alt="Hero" width="1200" height="600">
<!-- Below‑the‑fold gallery – lazy loaded -->
<div class="gallery">
<img src="photo1.jpg" alt="Photo 1" width="400" height="300" loading="lazy">
<img src="photo2.jpg" alt="Photo 2" width="400" height="300" loading="lazy">
<img src="photo3.jpg" alt="Photo 3" width="400" height="300" loading="lazy">
</div>
<!-- Embedded map – lazy loaded iframe -->
<iframe src="https://maps.example.com/embed" width="600" height="400" loading="lazy"></iframe>
Running this page in a modern browser will show the hero image immediately. The gallery images and the map iframe will only request their resources when the user scrolls near them.
Trade‑offs for LCP‑Sensitive Images
While lazy loading saves bandwidth, it can hurt LCP if applied to the largest above‑the‑fold element. The browser delays fetching, which delays the paint of that element. For LCP‑critical images you should:
- Keep
loading="eager"(or omit the attribute). The default is eager. - Consider
fetchpriority="high"on critical images, but avoid combining it withloading="lazy"as the signals conflict. - Use
sizesandsrcsetto deliver the optimal resolution, reducing download time.
In contrast, lazy loading iframe embeds often yields larger gains because third‑party scripts (e.g., Google Maps, YouTube) are deferred entirely.
Checklist & Testing
Before deploying, verify:
- Space reservation: Ensure every lazy image has
widthandheightoraspect-ratio. Use DevTools’ Layout Shift panel to confirm no CLS spikes. - Network behavior: Open DevTools Network tab, reload the page, and confirm that requests for lazy elements do not appear until you scroll near them.
- Performance audit: Run Lighthouse or PageSpeed Insights. The Defer offscreen images recommendation should no longer flag the lazy elements.
- Browser coverage: Check a compatibility matrix (e.g., MDN, caniuse) to confirm support for your target audience. Older browsers will load eagerly, which is acceptable.
When to Keep Eager Loading
Not every image should be lazy. The hero image, hero video thumbnail, or any element that satisfies LCP should remain eager. For background images set via CSS, Intersection Observer is still required if you want lazy behavior, as the loading attribute does not apply.
Remember that lazy loading does not help users who never scroll – those resources are simply never fetched, which is the intended behavior. Analytics that count "images loaded" will shift accordingly.
Actionable Takeaway
Adopt native lazy loading for all non‑critical images and iframes. Reserve loading="lazy" for below‑the‑fold content, and keep LCP‑critical elements eager. By following the checklist above you’ll reduce initial payload, improve Core Web Vitals, and avoid the pitfalls of layout shift.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.