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
- 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.
- Load when nearly visibleIntersectionObserver fires when a tile comes within 200 pixels of the view. Only then is the full image requested.
- 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));