You will learn how to defer the loading of offscreen images using the native HTML attribute loading="lazy", improving initial page load performance without JavaScript.
What it is
Lazy loading is a strategy where resources, such as images or iframes, are loaded only when they are needed. In modern web development, this primarily refers to deferring the download of images that are not currently visible in the user's viewport (the visible area of the web page). The browser handles the logic of determining when an image enters the viewport and triggers its download at that moment. This technique relies on the loading attribute, which accepts values like "eager" (default) or "lazy".
Why it matters
- Faster Initial Load: By reducing the number of HTTP requests made during the critical rendering path, the main content appears sooner.
- Better Bandwidth Usage: Users on mobile networks save data because they do not download images they never scroll to see.
- Improved Core Web Vitals: Lazy loading helps optimize Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS) by prioritizing above-the-fold content.
- Simplicity: It requires no external libraries or complex JavaScript observers, making it easy to implement and maintain.
Syntax or steps
To enable lazy loading for an image, add the loading="lazy" attribute directly to the <img> tag. Ensure you also provide explicit width and height attributes to prevent layout shifts while the image loads.
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lazy Loading Demo</title>
<style>
img {
display: block;
margin-bottom: 20px;
background-color: #f0f0f0; /* Placeholder color */
}
</style>
</head>
<body>
<h1>Scroll Down</h1>
<!-- Above the fold: Loads immediately -->
<img src="hero.jpg" alt="Hero Image" width="600" height="400">
<div style="height: 100vh;"></div> <!-- Spacer to force scrolling -->
<!-- Below the fold: Loads only when scrolled into view -->
<img src="product-1.jpg" alt="Product One" width="300" height="200" loading="lazy">
<img src="product-2.jpg" alt="Product Two" width="300" height="200" loading="lazy">
</body>
</html>
In this example, hero.jpg loads immediately because it lacks the loading attribute (defaulting to eager). The product images below the spacer div have loading="lazy". The browser will wait until these images approach the viewport before initiating their network requests.
Common mistakes
- Omitting Dimensions: If you do not specify
widthandheight, the browser reserves zero space initially. When the lazy-loaded image finally arrives, it pushes content down, causing Cumulative Layout Shift (CLS). - Lazy Loading Critical Images: Never apply
loading="lazy"to images that are part of the LCP (Largest Contentful Paint), such as hero banners or primary logos. This delays the perceived load time. - Assuming Universal Support: While widely supported now, older browsers may ignore the attribute. Always test on your target audience's devices.
- Using it for All Images: Applying lazy loading to small icons or sprites can sometimes increase overhead due to multiple separate requests compared to a single sprite sheet.
When to use it
Compare native lazy loading with JavaScript-based solutions like Intersection Observer.
| Feature | Native loading="lazy" |
JavaScript Intersection Observer |
|---|---|---|
| Complexity | Low (HTML attribute) | High (Requires JS setup) |
| Performance | Browser optimized | Depends on implementation |
| Control | Limited (browser decides threshold) | Full (custom thresholds/callbacks) |
| Best For | Standard image galleries, blogs | Custom animations, infinite scroll logic |
Use native lazy loading for standard content pages. Use JavaScript only if you need precise control over when loading starts or need to trigger side effects upon visibility.
Practice
Guided Exercise: Create a simple HTML page with three large placeholder images stacked vertically. Add loading="lazy" to the second and third images. Open the Network tab in your browser's Developer Tools, reload the page, and observe that only the first image request fires immediately. Scroll down to trigger the others.
Challenge: Try removing the width and height attributes from the lazy-loaded images. Observe the layout shift when the images load. Restore them to fix the issue.
Quick check
Question: Should you apply loading="lazy" to the main hero image at the top of your homepage?
Answer: No. Hero images are typically part of the Largest Contentful Paint (LCP). Lazy loading them delays their appearance, hurting performance metrics. They should load eagerly.
Summary
Native lazy loading via loading="lazy" is a powerful, low-effort optimization for deferring offscreen images. Always pair it with explicit dimensions to prevent layout shifts, and avoid applying it to critical above-the-fold content to ensure optimal Core Web Vitals scores.