Guides/ Images
hourglass_bottom

Lazy Loading Images: HTML, JavaScript & Best Practices

Lazy loading defers the download of off-screen images until the user scrolls near them. For a page with 20 images, this can reduce initial page weight by 70% and dramatically improve Time to Interactive. Here's how to implement it correctly.

April 2026 · 8 min read

Native Lazy Loading: One Attribute

As of 2020, all modern browsers support the loading attribute. For most sites, this is all you need — no JavaScript, no library.


Product





Hero



Intersection Observer: Custom Lazy Loading

When you need more control — fade-in effects, custom thresholds, or support for background images — Intersection Observer gives you precise control without polling.


Photo description



Blur Placeholder Technique

Show a tiny blurred version of the image while the full version loads. The technique uses a 20×20px version of the image (a few hundred bytes) as a placeholder, then swaps to full resolution.




Photo description

When NOT to Lazy Load

  • Hero images and LCP candidates — lazy loading the largest above-the-fold image is the most common lazy loading mistake. It delays LCP by 500ms–1s+ and directly harms your Core Web Vitals score.
  • Images within the first viewport — any image visible without scrolling (approximately the first 800px of page height) should not be lazy loaded. Use loading='eager' or simply omit the attribute.
  • Critical UI images — logo, profile avatar, product thumbnail in the hero card — these affect perceived performance. Load them immediately.
  • Images in carousels that autoplay immediately — if your carousel auto-advances, the second slide's image needs to be ready, not deferred.

Frequently Asked Questions

Does native loading=lazy affect SEO?
No — Google's crawler renders JavaScript and respects loading=lazy. Images with lazy loading are indexed normally. Google also reports that lazy loading images doesn't negatively impact crawling or indexing.
What is the rootMargin in Intersection Observer?
rootMargin extends the 'viewport' used for intersection detection. A rootMargin of '200px' means images start loading when they're 200px away from the visible viewport — before they scroll into view. This prevents blank images as the user scrolls. 100–300px is a good default.
Should I use a JavaScript lazy loading library in 2026?
Probably not — native loading=lazy covers 95%+ of browsers. Only use a JS library if you need specific features: blur placeholders, custom animations, background image lazy loading, or Safari < 15.4 support.
How do I lazy load CSS background images?
CSS background images don't support the loading attribute. Use Intersection Observer to add a class when the element enters the viewport, then set the background-image in that class. This defers the image until the element is visible.