Why Image Lazy Loading Matters
Images are among the largest resource types on web pages. According to HTTP Archive statistics, images account for over 50% of the average webpage's total weight. On a typical news or e-commerce page, dozens of images may load simultaneously, significantly increasing initial page load time, wasting bandwidth, and consuming data. The core idea of image lazy loading is: only load images within the user's current visible area (viewport), deferring other images until the user scrolls near them. This approach dramatically reduces initial page load time, improving user experience and Core Web Vitals.
1. Technical Overview
1.1 How It Works
Lazy loading is implemented through the following key steps:
- Replace Image Source: In HTML, replace the
<img>tag'ssrcattribute with a placeholder or blank, storing the real image URL in a custom attribute likedata-src - Monitor Scroll Position: Listen for page scroll events or use the Intersection Observer API to detect when images enter the viewport
- Load Real Image: When an image enters the viewport, assign
data-srcvalue to thesrcattribute, triggering the browser to load - Handle Load Completion: After the image loads, remove placeholder styles and display the real image
1.2 Performance Benefits
| Scenario | Without Lazy Loading | With Lazy Loading | Improvement |
|---|---|---|---|
| Initial Page Load Time | 3.5s | 1.8s | 48% improvement |
| Total Page Transfer Size | 2.8MB | 0.6MB | 78% reduction |
| Lighthouse Performance Score | 62 | 94 | 32-point improvement |
2. Implementation Approaches
2.1 Native Lazy Loading (Recommended)
Starting from Chrome 76, browsers natively support image lazy loading — just add the loading="lazy" attribute to <img> tags:
<img src="example.jpg" loading="lazy" alt="Example image" />
<!-- Also supports iframe lazy loading -->
<iframe src="example.html" loading="lazy"></iframe>
Advantages: Zero JavaScript code, browser automatically optimizes load timing, best performance.
Disadvantages: Not supported by all browsers (Safari 15.4+ required).
2.2 Intersection Observer API
For scenarios needing more control, use the Intersection Observer API:
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
document.querySelectorAll('img.lazy').forEach(img => {
imageObserver.observe(img);
});
| Approach | Complexity | Performance | Maintainability | Use Case |
|---|---|---|---|---|
| Native lazy attribute | Low | Excellent | High | General scenarios |
| Intersection Observer | Medium | High | Medium | Custom loading effects needed |
| Third-party JS library | Low | Medium | Medium | Legacy browser compatibility |
2.3 Third-Party Libraries
- Lozad.js: Lightweight (1KB), Intersection Observer based
- lazysizes: Most feature-rich, supports responsive images and auto-calculation
- vanilla-lazyload: Simple and easy, supports images, iframes, and video
2.4 The Recommended Production Combo
You do not have to pick one; combine them — native attributes as the baseline, Observer for enhancement. A low-friction template:
<img
src="placeholder.svg"
data-src="photo-800.jpg"
data-srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
data-sizes="(max-width: 600px) 100vw, 800px"
loading="lazy"
decoding="async"
width="800" height="450"
class="lazy"
alt="Article image"
/>
Fixing width/height reserves the aspect ratio (paired with CSS aspect-ratio) so space is held before the image loads, avoiding layout shift that drags down CLS; decoding="async" keeps decoding off the main thread; srcset/sizes let the browser pick the right size for the viewport, so mobile stops downloading desktop-size images. The Observer code only swaps data-src/data-srcset for the real URLs.
3. Advanced Optimization Techniques
// Combining with placeholder technique (BlurHash)
const img = new Image();
img.onload = () => {
// First show blurred thumbnail
placeholder.style.filter = 'blur(20px)';
// Fade in high-res image after load
highResImg.classList.add('loaded');
};
img.src = highResUrl;
4. Important Considerations
- Above-fold images should not use lazy loading: Images in the initial viewport should load normally
- Reserve image placeholder space: Set aspect-ratio to prevent layout shifts
- Consider SEO impact: Ensure search engine crawlers can access images
- Compatibility handling: Provide fallback for browsers without native lazy loading
- Image decoding optimization: Use
decoding="async"attribute for async image decoding
Common Questions
- Does lazy loading hurt SEO: Google explicitly supports
loading="lazy"and can crawl lazy-loaded images; the key is that the DOM carries real URLs (srcor a parseabledata-src) — do not let images depend entirely on JS injection. - Should above-the-fold images be lazy-loaded: no. Above-the-fold images should load immediately, or LCP suffers.
- Does lazy loading conflict with a CDN: no; pairing them is actually recommended — lazy loading cuts the number of requests and the CDN raises hit rates.
A Real Case
A photography blog's gallery page carried 40 images at 2MB each. Before the change, initial transfer was about 8MB and mobile users waited over ten seconds. Three fixes brought first-paint transfer down to 1.2MB: thumbnails using loading="lazy" plus srcset for width-based delivery, Observer-based loading for below-the-fold images, and low-quality image placeholders (LQIP) on list pages. Lighthouse Performance went from 54 to 91 and bounce rate fell 6 points in a quarter. Lazy loading is not "add one attribute and done"; it pays off when combined with image compression and responsive sizing.
5. Summary
Image lazy loading is one of the simplest and most effective techniques for improving web performance. For modern browsers, directly using the loading="lazy" attribute is recommended. For custom loading effects or additional functionality, the Intersection Observer API provides sufficient flexibility and performance. Regardless of the approach, properly configured lazy loading significantly improves user experience and core performance metrics.
Reference: MDN loading attribute https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/loading ; MDN Intersection Observer https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API ; web.dev on image lazy loading https://web.dev/articles/browser-level-image-lazy-loading