All questions

Lazy Load Images

Premium

Lazy Load Images

Loading every image on a long page up front wastes bandwidth on pictures the user may never scroll to. The fix is lazy loading: ship the markup with the real URL parked in data-src and an empty src, then swap it in only when the image is about to enter the viewport. IntersectionObserver makes this cheap — it watches elements against the viewport and calls you when they cross in, no scroll-handler math required.

Implement lazyLoadImages(root, options). Observe each img[data-src] under root, and on intersection move data-srcsrc, then stop watching it. See MDN: lazy loading.

Signature

function lazyLoadImages(root, options) {
  // returns the IntersectionObserver (or null when falling back)
}

Examples

<img data-src="hero.jpg" />   <!-- no src yet: nothing downloads -->
lazyLoadImages(document.body, { rootMargin: '200px' });
// as the <img> nears the viewport (200px early):
//   img.src = 'hero.jpg'; the browser fetches it; data-src is removed;
//   the observer stops watching that image.

Notes

  • Only img[data-src] — leave images that already have a src alone.
  • Load once, then unobserve — after swapping, stop observing that image so it never fires again.
  • rootMargin preloads early — a positive margin (e.g. '200px') starts the fetch just before the image scrolls into view, avoiding a visible pop-in.
  • Graceful fallback — if IntersectionObserver isn't available, load every image immediately so nothing stays blank.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium