🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Lazy Loading Images: Deferring What Isn't Visible Yet

Master the native loading="lazy" attribute for deferring off-screen images, the critical exception for above-the-fold LCP candidates, and why pairing lazy loading with explicit dimensions prevents layout shift.

Total XP: 0|💻 html XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

Lazy Loading

Native deferral, the key exception.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Native lazy loading lets a browser skip downloading off-screen images until they're actually about to be needed, with a single HTML attribute — but knowing when not to use it matters just as much as knowing how.

1Native, Zero-JavaScript Deferral

Before browsers implemented this natively, deferring off-screen image downloads required a custom JavaScript implementation using the Intersection Observer API to detect when an image was nearing the viewport, then dynamically setting its src attribute — meaningful implementation complexity for a fairly common need.

loading="lazy" on an <img> (or <iframe>) achieves the same outcome natively: the browser applies its own built-in threshold logic to defer that resource's download until it's estimated to be needed soon, based on scroll position — with zero JavaScript, and zero added implementation complexity.

<img src="product-14.jpg" alt="Blue running shoe" loading="lazy">
localhost:3000
✓ Deferred Until Near-ViewportThe browser handles all threshold and timing logic natively, with zero JavaScript required.

2The Critical Exception: Never For Above-The-Fold LCP Images

The single most damaging lazy-loading mistake is applying loading="lazy" to an image already visible in the initial viewport — most critically, a hero image likely serving as the page's Largest Contentful Paint candidate. Since that image is already on screen at load time, deferring its download provides zero benefit and instead actively delays exactly the render event LCP measures.

For genuinely above-the-fold, LCP-critical images, the correct approach is the opposite of lazy loading: use fetchpriority="high" to signal the browser should prioritize downloading it as early and eagerly as possible, ensuring it renders as fast as the network allows.

<!-- Wrong: delays the LCP candidate -->
<img src="hero.jpg" loading="lazy">

<!-- Correct: prioritize it instead -->
<img src="hero.jpg" fetchpriority="high">
localhost:3000
⚠ Opposite Treatment For Above-The-Fold ImagesNever lazy; instead, prioritize LCP-critical images to load as fast as possible.

3Pairing With width/height To Prevent Layout Shift

A lazily-loaded image's file hasn't been downloaded yet, so unless its dimensions are declared explicitly, the browser has no way to know how much space to reserve for it — exactly the missing-dimensions CLS scenario covered in the Core Web Vitals lesson. Since a lazy image typically loads in later, often while a user is actively scrolling and reading nearby content, an un-reserved space produces a visible, disruptive shift exactly when the user is engaged.

Always pairing loading="lazy" with explicit width and height attributes (or a matching CSS aspect-ratio) ensures the browser reserves the correct space immediately, so the eventual image load-in causes zero layout disruption.

<img src="product-14.jpg" alt="..." loading="lazy" width="400" height="300">
localhost:3000
Reserved space:
400×300 box, before the file even loads

4Step-by-Step Breakdown

Don't Download What The User Can't See Yet. A long product listing page might contain 50 images, but a user's initial viewport can only show 4 or 5 of them. Downloading all 50 immediately wastes bandwidth and competes for network priority with content that actually matters right now — native lazy loading fixes this with a single HTML attribute.

loading="lazy" Defers Off-Screen Images Natively. Adding loading="lazy" to an <img> tells the browser to defer downloading that image until it's about to scroll into the viewport, using a built-in threshold — no JavaScript, no Intersection Observer implementation required for the common case.

Native Lazy Loading. What's required to implement basic native image lazy loading in a modern browser?

  • A custom JavaScript Intersection Observer implementation
  • A single HTML attribute, loading="lazy", with no JavaScript needed
  • A dedicated third-party lazy-loading library

Never Lazy-Load The LCP Candidate. Applying loading="lazy" to an above-the-fold hero image — likely the page's LCP candidate — actively delays its download until the browser would otherwise start it, directly hurting LCP. This is the single most damaging lazy-loading mistake.

The Critical Exception. Why is applying loading="lazy" to a page's main above-the-fold hero image actively harmful?

  • It's not harmful; lazy loading always helps
  • It delays the download of what's likely the page's LCP candidate, directly hurting that metric
  • It breaks the image's alt text from being read correctly

Lazy Loading And Layout Shift Prevention Work Together. Because a lazily-loaded image's file hasn't downloaded yet, the browser doesn't inherently know its dimensions until it does — making explicit width/height attributes (from the HTML Performance module's CLS lesson) essential alongside loading="lazy" to reserve space and prevent layout shift as it loads in.

Lazy Loading And CLS. Why is it especially important to include width/height attributes on lazily-loaded images specifically?

  • It's not more important for lazy images than any other image
  • Reserved space prevents surrounding content from shifting when the deferred image finally loads in
  • loading="lazy" is invalid HTML without them

Lazy Loading Mastered. You now know how to defer off-screen images natively with loading="lazy", why this must never be applied to an above-the-fold LCP candidate, and why pairing it with explicit width/height attributes prevents layout shift as deferred images load in — completing the Modern Images module.

Lazy-Load An Offscreen Image. loading="lazy" combined with decoding="async" defers work until the image is actually needed.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Lazy Loading Has No Effect On alt Text Announcement Timing For Screen Reader Users

The accessible name is present in the DOM immediately regardless of whether the underlying image file has downloaded yet, so lazy loading doesn't create any accessibility timing concern for assistive technology.

SEO Implications

  • 1

    Correct Lazy Loading Reduces Initial Page Weight, Directly Supporting Faster Overall Load Metrics

    Deferring dozens of below-the-fold images on a long listing page meaningfully reduces initial network contention, indirectly benefiting how quickly critical above-the-fold content, including the real LCP candidate, can load.

  • 2

    Misapplied Lazy Loading On The LCP Candidate Is A Direct, Measurable Ranking-Relevant Regression

    Since Core Web Vitals are a confirmed ranking factor and LCP is one of its three metrics, this specific mistake has a direct, traceable path to real search visibility harm, not just a theoretical concern.

Best Practices

Apply loading="lazy" To Every Image Confirmed To Be Below The Initial Viewport

It's a single, free attribute that meaningfully reduces initial page weight and network contention for any image not immediately needed, with no meaningful downside for genuinely off-screen content.

Never Apply loading="lazy" To A Page's Hero Image Or Any Other Likely LCP Candidate

This single exception is critical — misapplying lazy loading here directly and measurably regresses the most heavily-weighted, ranking-relevant Core Web Vitals metric.

Frequent Bugs

THE BUG

A page's LCP score regressed noticeably after a well-intentioned 'add lazy loading everywhere' pass across the codebase.

THE FIX

Audit for loading="lazy" mistakenly applied to above-the-fold hero or LCP-candidate images, and remove it (optionally adding fetchpriority="high") for those specific images.

THE BUG

A product grid shows visible content jumping as users scroll and lazy images load in.

THE FIX

Add explicit width/height attributes (or matching CSS aspect-ratio) to every lazily-loaded image, reserving its display space before the file downloads.

Real-World Examples

A Correctly Mixed Lazy/Eager Strategy

A product listing page where the hero is eagerly prioritized and every product grid image below it is lazily loaded with reserved dimensions.

<img src="hero.jpg" alt="Summer sale" fetchpriority="high" width="1200" height="400">

<!-- Product grid, repeated for each item -->
<img src="product-1.jpg" alt="Blue sneaker" loading="lazy" width="300" height="300">

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Applying loading="lazy" to an above-the-fold hero or LCP-candidate image

<img src="hero.jpg" fetchpriority="high" alt="...">

The Solution //

Never lazy-load above-the-fold images; use fetchpriority="high" to prioritize them instead.

The Error //

Omitting width/height on lazily-loaded images

<img src="..." loading="lazy" width="400" height="300" alt="...">

The Solution //

Always pair loading="lazy" with explicit dimensions to reserve space and prevent layout shift.

Lesson Glossary

[01]loading="lazy"

A native attribute deferring off-screen image download.

Code Preview
<img loading="lazy">

[02]LCP Candidate

The element likely measured as Largest Contentful Paint.

Code Preview
Never lazy-load this

[03]fetchpriority

An attribute prioritizing eager download of critical resources.

Code Preview
fetchpriority="high"

[04]Intersection Observer

The legacy JS API used before native lazy loading existed.

Code Preview
No longer required for basic cases

Continue Learning