How to Lazy Load Images for Better Performance
Implement native and JavaScript-based lazy loading. Reduce initial page weight, improve LCP, and handle edge cases.
- Implement native and JavaScript-based lazy loading.
- What Lazy Loading Does.
- Native Browser Lazy Loading.
- JavaScript Lazy Loading.
- Common Lazy Loading Mistakes.
What Lazy Loading Does
Lazy loading defers downloading off-screen images until the user scrolls near them. On a page with 30 images, only the 3–5 visible in the initial viewport load immediately; the rest load on demand. This reduces initial page weight by 60–80% for image-heavy pages, dramatically improving Time to Interactive. Modern lazy loading is simple: add loading="lazy" to your img tags, and the browser handles everything.
Native Browser Lazy Loading
Native lazy loading with loading="lazy" is supported in all modern browsers. Just add the attribute: <img src="photo.webp" loading="lazy" alt="..." width="800" height="600">. The browser uses built-in thresholds to start loading before the image enters the viewport. Always include width and height to reserve space and prevent CLS. Apply loading="lazy" to every img EXCEPT your above-the-fold hero/LCP image.
JavaScript Lazy Loading
JavaScript-based lazy loading (IntersectionObserver) gives more control: custom thresholds, placeholder effects, load priority, and CSS background image support. The pattern: observe each image, when it enters threshold, set src from data-src, unobserve. Libraries like lazysizes handle edge cases, but vanilla IntersectionObserver is only 10 lines of code. Use the Image Compressor to optimize images before implementing lazy loading.
Common Lazy Loading Mistakes
Common mistakes: lazy loading the LCP hero image (delays the most important metric), not setting dimensions (causes CLS), using a JS library when native loading="lazy" suffices, setting thresholds too aggressively (visible loading delay), and not handling the no-JavaScript case. Always set a real src or use a noscript fallback.