HTML / CSS

Lazy Loading in HTML and CSS: Enhancing Performance and User Experience

I once profiled a landing page that loaded 40 images on first paint. The hero image fought for bandwidth with a carousel image sitting 3000 pixels below t...

28 Dec 2024

Lazy Loading in HTML and CSS: Enhancing Performance and User Experience

I once profiled a landing page that loaded 40 images on first paint. The hero image fought for bandwidth with a carousel image sitting 3000 pixels below the fold. The page took 8 seconds to become interactive. Lazy loading cut that in half.

Lazy loading defers the loading of off-screen resources until the user actually needs them. Instead of downloading everything upfront, the browser only fetches what's visible. The rest loads as you scroll.

Why it works

Your browser has limited bandwidth and a limited number of concurrent connections. Every resource you load competes with every other resource. By deferring images, iframes, and heavy assets that aren't visible yet, you free up bandwidth for the content the user is actually looking at.

The wins are immediate:

  • Faster initial page load. The critical content renders sooner.
  • Less bandwidth consumed. Users on slow connections or metered data benefit the most.
  • Better Core Web Vitals. LCP and FID improve when the browser isn't juggling dozens of off-screen requests.

The simplest approach: the loading attribute

Modern browsers support loading="lazy" natively on images and iframes. No JavaScript required.

Text
<img src="hero.jpg" alt="Hero" loading="eager">
<img src="below-fold.jpg" alt="Feature" loading="lazy">

The browser decides when to start loading based on the element's distance from the viewport. For images above the fold, use loading="eager" (or omit the attribute entirely) to avoid delaying critical content.

Lazy loading iframes

Embedded content like YouTube videos or maps are expensive. A single YouTube embed can pull in over 1MB of resources. Lazy loading iframes is one of the highest-impact performance wins you can make.

Text
<IFRAMETAG
    width="560"
    height="315"
    src="https://www.youtube.com/embed/dQw4w9WgXcQ"
    title="YouTube video player"
    loading="lazy"
></IFRAMETAG>

The trade-offs

Lazy loading isn't free. If you lazy load images above the fold, the user sees a blank space while the image fetches. That's worse than eager loading.

The loading="lazy" attribute also has no universal standard for "how close to the viewport" triggers the load. Different browsers use different thresholds. If you need precise control, use IntersectionObserver in JavaScript instead.

For critical above-the-fold content, always load eagerly. For everything else, lazy load. That's the rule I follow.