javascript 39 lines · 8 steps

How lazy image loading works

Defer loading images until they near the viewport using IntersectionObserver, with a graceful fallback.

Explained by highlit
1function initLazyLoad(root = document) {
2 const images = root.querySelectorAll('img[data-src]');
3 
4 if (!('IntersectionObserver' in window)) {
5 images.forEach(loadImage);
6 return;
7 }
8 
9 const observer = new IntersectionObserver((entries, obs) => {
10 for (const entry of entries) {
11 if (!entry.isIntersecting) continue;
12 loadImage(entry.target);
13 obs.unobserve(entry.target);
14 }
15 }, {
16 rootMargin: '200px 0px',
17 threshold: 0.01
18 });
19 
20 images.forEach((img) => observer.observe(img));
21}
22 
23function loadImage(img) {
24 const { src, srcset } = img.dataset;
25 
26 img.addEventListener('load', () => {
27 img.classList.add('is-loaded');
28 }, { once: true });
29 
30 img.addEventListener('error', () => {
31 img.classList.add('is-error');
32 }, { once: true });
33 
34 if (srcset) img.srcset = srcset;
35 if (src) img.src = src;
36 
37 delete img.dataset.src;
38 delete img.dataset.srcset;
39}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1IntersectionObserver lets you react to viewport proximity without scroll listeners or manual math.
  2. 2Feature-detect and fall back so the page works even where the API is missing.
  3. 3Unobserving after a hit and using once listeners keeps work one-shot and avoids leaks.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How lazy image loading works — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code