HTML Beginner

Lazy load images without JavaScript

Lazy loading images used to mean writing an IntersectionObserver, swapping src attributes, and handling edge cases per browser. One attribute does it all now.

Modern
1 attribute
1<!-- Above the fold: no lazy -->
2<img src="hero.jpg" alt="Hero" />
3
4<!-- Below the fold: lazy load -->
5<img src="photo.jpg" alt="Photo" loading="lazy" />
6<iframe src="map.html" loading="lazy"></iframe>
Old JS required
1<!-- HTML: data-src instead of src -->
2<img data-src="photo.jpg" class="lazy" />
3const observer = new IntersectionObserver(([entry]) => {
4  if (entry.isIntersecting) {
5    entry.target.src = entry.target.dataset.src;
6    observer.unobserve(entry.target);
7  }
8});
9document.querySelectorAll('.lazy').forEach(img => observer.observe(img));
Widely available Since 2023 95% global usage

This feature is well established and works across many devices and browser versions. It has been available across browsers since 2023.

77+
121+
16.4+
79+
scroll down inside the frame to trigger lazy loading
Above the fold β€” loads immediately
<img src="…"> β€” no loading attribute
↓ scroll down ↓
<img src="…" loading="lazy">
Not yet loaded…
Scroll down to trigger lazy load
Kinsta

Your first month is free

Managed WordPress hosting for faster sites.

Learn more
⚑

One attribute

Add loading="lazy" to any img or iframe. The browser decides when to fetch it based on scroll position and network conditions.

✦

Faster initial load

Off-screen images are not fetched on page load. The browser only requests them as the user scrolls near them, saving bandwidth and speeding up LCP.

∞

Works on iframes too

loading="lazy" works on iframe elements as well. Useful for maps, embedded videos, and third-party widgets that would otherwise block rendering.

JS Removed
9 lines β†’ 1
No IntersectionObserver
Old Approach
IntersectionObserver
data-src swap on scroll
Modern Approach
loading="lazy"
Native browser deferral

How it works

The loading attribute tells the browser how to prioritize fetching the resource. loading="lazy" defers the fetch until the image or iframe is near the viewport. loading="eager" is the default β€” fetch immediately regardless of position.

Never add loading="lazy" to above-the-fold images. Those need to load immediately for good LCP scores. Apply it only to images that start off-screen. A good rule: the first image on a page should not be lazy.

Always include width and height attributes on lazy images. Without them the browser does not know the image dimensions before it loads, causing layout shift when the image finally appears.

New CSS drops.

Join 600+ readers who've survived clearfix hacks.

ESC