Vanilla JavaScript Projects

Project 84, Content and data

Blur-up Lazy Images

Pages with many photos can load in a flash. Each image starts as a tiny blurred preview and sharpens only when you are about to see it.

Main API
IntersectionObserver
Placeholder
20 pixel image
Dependencies
None
Your browser
Checking

Scroll the gallery

Scroll inside the box. Watch the blurry previews sharpen and the counters change. Switch to native lazy loading to compare.

0full images loaded
0still waiting
0 KBsaved so far, roughly

How it works

  1. Start with a tiny imageEach tile gets a 20 pixel wide version of the photo as a background, blurred. It is about 1 KB and shows the colours straight away.
  2. Load when nearly visibleIntersectionObserver fires when a tile comes within 200 pixels of the view. Only then is the full image requested.
  3. Reserve the spaceEvery tile has a fixed 3 by 2 aspect ratio, so the page never jumps as images arrive. That keeps layout shift scores low.
const io = new IntersectionObserver((entries) => {
  for (const e of entries) {
    if (!e.isIntersecting) continue;
    io.unobserve(e.target);
    const img = e.target.querySelector("img");
    img.src = img.dataset.src;                      // full image
    img.onload = () => e.target.classList.add("done"); // fade in over blur
  }
}, { rootMargin: "200px" });
tiles.forEach((t) => io.observe(t));