How to lazy load images (and why your site feels slow without it)

Your website loads every single image the moment someone opens the page. All of them. Even that footer graphic nobody scrolls to. That's like cooking a 7-course meal when your guest only wanted coffee.

Lazy loading fixes this. It tells the browser: "Hey, only load images when the user is about to see them." Simple idea, massive impact.

The one-line fix

HTML now has a built-in way to do this. No JavaScript, no libraries, no npm packages with 47 dependencies:

<img src="photo.jpg" alt="A lazy cat" loading="lazy" />

That's it. Add loading="lazy" to your <img> tags and the browser handles the rest. It watches the scroll position and loads images just before they enter the viewport.

When NOT to lazy load

Don't slap loading="lazy" on everything. Your hero image — the big one at the top of the page — should load immediately. If you lazy load it, users see a blank space for a split second, and that feels broken.

For above-the-fold images, use loading="eager" (which is the default anyway) or just leave the attribute off:

<img src="hero-banner.jpg" alt="Welcome" loading="eager" />

What about background images in CSS?

This is where it gets trickier. loading="lazy" only works on <img> tags. For CSS background images, you need a small workaround — use a class that gets added via JavaScript when the element is near the viewport:

.lazy-bg {
  background-image: none;
}
.lazy-bg.visible {
  background-image: url('big-background.jpg');
}
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
});

document.querySelectorAll('.lazy-bg').forEach(el => observer.observe(el));

It's a few extra lines, but the Intersection Observer API is supported everywhere now. No polyfills needed.

Does this help SEO?

Yes, indirectly. Google cares about page speed, especially on mobile. If your page loads 2MB of images upfront instead of 200KB, your Core Web Vitals scores tank — and those feed directly into rankings.

I saw a landing page go from a 45 to a 78 on PageSpeed Insights just by adding lazy loading to 12 product images. No other changes.

TL;DR: Add loading="lazy" to images below the fold. Keep hero images eager. Your page loads faster, users are happier, Google notices.