JA EN

Image Lazy Loading Implementation Guide - Choosing Between loading=lazy and IntersectionObserver

· About 9 min read

Lazy Loading Fundamentals and Performance Impact

Image lazy loading is a technique that initiates image downloads only when they approach the user's viewport. For a page containing 20 images, only the 2-3 images in the first viewport load initially, with the rest loading progressively as the user scrolls.

The performance impact is dramatic. On image-heavy pages, initial load network requests can be reduced by 70-80%. This concentrates browser network bandwidth on critical resources like HTML, CSS, and JavaScript, significantly improving Time to Interactive (TTI). Real-world measurements show pages with 20 images reducing initial page load time from 3.2 seconds to 1.4 seconds after implementing lazy loading.

However, lazy loading is not a universal solution. Applying it to first-viewport images actually worsens LCP. Images that users see first must load immediately, so lazy loading targets should be limited to below-the-fold images. Misjudging this boundary degrades Core Web Vitals scores and negatively impacts SEO.

Implementation with Native loading Attribute

The HTML loading attribute provides browser-native lazy loading functionality. As of 2024, all major browsers support it, making it the simplest method to achieve lazy loading without JavaScript.

Usage is extremely straightforward:

The loading attribute accepts three values. lazy defers loading until the image approaches the viewport. eager initiates loading immediately (default behavior). auto delegates the decision to the browser.

A key characteristic of native lazy loading is that the browser automatically determines the threshold for when to begin loading. In Chrome, this threshold varies dynamically based on connection speed. On fast connections, loading begins approximately 1250px before the viewport; on slow connections (3G equivalent), approximately 2500px before. This adaptive behavior minimizes wait time when users scroll to images.

Critical requirement: When using loading="lazy", always specify width and height attributes. Without these, the browser cannot determine image dimensions in advance, causing layout shift (CLS).

Advanced Control with IntersectionObserver

The IntersectionObserver API enables fine-grained control impossible with the native loading attribute. It's suitable when you need to customize loading thresholds, animation effects, and placeholder management for detailed UX crafting.

Basic implementation pattern:

The rootMargin option controls the loading threshold. Specifying '200px 0px' initiates loading when images enter within 200px above or below the viewport. Larger values make scrolling smoother but increase initial requests - a tradeoff to consider.

The threshold option controls firing based on what percentage of the image has entered the viewport. threshold: 0.1 fires when 10% of the image is visible. This is useful for applying fade-in animations as images appear on gallery pages.

Placeholder Strategies and UX Optimization

What users see while waiting for lazy-loaded images significantly impacts UX. Blank spaces make layouts appear unstable, while appropriate placeholders communicate that "an image will appear here."

Major placeholder strategies:

Apply fade-in animations for the transition from placeholder to actual image for smooth switching. Combining opacity with transition and changing to opacity: 1 on the image's onload event is the standard implementation. Keep animation duration to 200-300ms to avoid giving users the impression of waiting.

LCP Impact and Correct Application Scope

The biggest pitfall of lazy loading is applying it to LCP (Largest Contentful Paint) candidate images. LCP measures the render time of the largest content element in the first viewport, which is typically the hero image or main visual on most pages.

Setting loading="lazy" on LCP images causes the browser to defer the download, worsening LCP scores by hundreds of milliseconds to several seconds. Google's Lighthouse warns about "lazy loading on LCP image," and clear negative impacts are confirmed in field data (CrUX) as well.

Criteria for correct application scope:

For LCP images, set fetchpriority="high" instead of loading="lazy", and additionally instruct preloading with <link rel="preload" as="image"> to maximize LCP improvement. This polarized strategy of "prioritize critical images, defer everything else" is fundamental to Core Web Vitals optimization.

Framework-Specific Implementation and Considerations

Modern frontend frameworks each provide their own image optimization components. Leveraging these significantly simplifies lazy loading implementation.

Next.js's next/image component has lazy loading enabled by default. Setting the priority property to true disables lazy loading and automatically applies fetchpriority="high" and preload. Always set priority for LCP images.

React custom implementations typically create a custom hook managing IntersectionObserver with useRef and useEffect. Calling observer.disconnect() on component unmount to prevent memory leaks is essential.

Static sites (HTML + CSS + JS) should use native loading="lazy" as the baseline, adding IntersectionObserver only when placeholders or animations are needed. Native attributes integrate with the browser's optimization engine, tending to outperform JavaScript implementations.

Across all frameworks, pre-determining image width and height (or aspect ratio) is key to CLS prevention. When dimensions of dynamically loaded images are unknown, include dimension information in API responses or wrap images in fixed aspect-ratio containers.

Related Articles

Responsive Images Implementation Guide - Complete Guide to srcset, sizes, and picture Elements

Learn how to serve optimal images based on device screen size and resolution with detailed code examples for responsive image implementation.

Web Image File Size Optimization Strategy - Techniques for Reducing Size While Maintaining Quality

Systematically learn image file size optimization methods for maximizing web performance, from format selection to metadata removal.

How Browser Image Processing Works - Canvas API, ImageData, and Web Workers Guide

Technical explanation of client-side image processing in browsers. Learn about pixel manipulation with Canvas API, ImageData structure, off-thread processing with Web Workers, and OffscreenCanvas usage.

Core Web Vitals and Image Optimization - Practical Methods to Improve LCP, CLS, and INP

How images impact Core Web Vitals metrics (LCP, CLS, INP) and concrete improvement techniques. Data-driven performance optimization priorities and implementation patterns explained.

Web Image Performance Audit - Practical Guide to Core Web Vitals Improvement

Learn how to audit image impact on web performance. Covers LCP improvement, CLS prevention, and transfer size reduction with actionable techniques.

Image Loading Strategy Design - Mastering preload, fetchpriority, and decoding

Deep dive into three HTML attributes that optimize image loading. Learn the correct usage and combinations of preload, fetchpriority, and decoding for LCP improvement.

Related Terms