Defer Offscreen Images in Magento 2: Complete Lazy Loading Guide
[Updated: March 19, 2026]
Google PageSpeed Insights flags "Defer offscreen images" on almost every Magento store. The fix is straightforward, but choosing the wrong method wastes time and can hurt your Largest Contentful Paint score.
This guide covers three methods to defer offscreen images in Magento 2, when each method fits, and how to verify results.
Key Takeaways
-
Native
loading="lazy"is the simplest method and works without extensions or custom JavaScript -
The IntersectionObserver API gives fine-grained control for custom themes and complex layouts
-
Third-party extensions add admin panel configuration and advanced features like placeholder images
-
Never lazy load above-the-fold images, hero banners, or your LCP element
-
Core Web Vitals thresholds for 2026: LCP under 2.5 seconds, INP under 200 milliseconds, CLS under 0.1
What Are Offscreen Images?
Offscreen images = Images below the visible viewport that load before the user scrolls to them. They add unnecessary weight to the initial page load, slowing down Time to Interactive and hurting your Core Web Vitals scores.
Perfect for: Magento stores with product catalogs, category pages with 20+ images, CMS pages with media-heavy content
Not ideal for: Pages with fewer than 5 images total, single-product landing pages with all images above the fold
When a browser loads a Magento page, it downloads every image on that page by default. On a category page with 40 product thumbnails, the browser fetches all 40 images even though the visitor sees only 8 to 12 without scrolling.
Google PageSpeed Insights identifies these images and reports the potential savings in kilobytes. The "Defer offscreen images" suggestion means: load images only when they approach the viewport.
Why Deferring Offscreen Images Matters
A one-second delay in page load time can reduce conversions by up to 7%. For Magento stores with hundreds of product images, the impact compounds fast.
Core Web Vitals Impact
Google uses three Core Web Vitals as ranking signals. These thresholds are based on the 75th percentile of real user data from the Chrome User Experience Report (CrUX), not lab tests:
| Metric | Threshold (Good) | How Offscreen Images Affect It |
|---|---|---|
| LCP (Largest Contentful Paint) | Under 2.5s | Competing image requests delay the largest visible element |
| CLS (Cumulative Layout Shift) | Under 0.1 | Images without dimensions cause layout shifts as they load |
| INP (Interaction to Next Paint) | Under 200ms | Heavy image downloads block the main thread |
Only 48% of mobile pages pass all three Core Web Vitals (2025 Web Almanac). Deferring offscreen images is one of the highest-impact fixes.
Bandwidth and Server Load
Every image request hits your server. On a Magento category page, 40 simultaneous image requests during initial load create unnecessary server strain. Lazy loading spreads these requests over time as the user scrolls, reducing peak server load and TTFB.
Method 1: Native HTML loading="lazy" (Recommended)
The simplest approach uses the browser's built-in lazy loading. Add the loading="lazy" attribute to any img tag:
<img src="product-image.jpg"
loading="lazy"
width="300"
height="300"
alt="Product name">
All major browsers support this attribute: Chrome, Firefox, Safari, and Edge. No JavaScript required. Browsers use adaptive distance thresholds to decide when loading starts: Chromium triggers at 1,250px before the viewport on 4G connections and 2,500px on 3G or slower, so images are ready before the user scrolls to them.
Implementation in Magento 2
In Magento 2.4.x, edit your theme's image templates. The key files:
Category page thumbnails (catalog/product/list.phtml):
<img src="<?= $productImage->getImageUrl() ?>"
loading="lazy"
width="<?= $productImage->getWidth() ?>"
height="<?= $productImage->getHeight() ?>"
alt="<?= $block->escapeHtmlAttr($productImage->getLabel()) ?>">
CMS blocks and widgets: Add loading="lazy" to img tags in your CMS content through the admin panel or via layout XML overrides.
Page Builder images: Page Builder renders img tags at runtime through its JavaScript templates. To add loading="lazy" to Page Builder images, create a layout XML override or a small custom module that modifies the rendered output.
Critical Rule: Never Lazy Load the LCP Element
The Largest Contentful Paint element is the biggest visible element when the page first loads. On most Magento pages, this is the hero banner or the first product image. Lazy loading your LCP element delays its render and destroys your LCP score.
Use loading="eager" (or omit the attribute) for:
- Hero banners and sliders
- First product image on product detail pages
- Category header images
- Any image visible without scrolling
Method 2: IntersectionObserver API
For custom Magento themes or complex layouts that need precise control, the IntersectionObserver API detects when elements enter the viewport:
document.addEventListener('DOMContentLoaded', function() {
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
}, {
rootMargin: '200px 0px' // Start loading 200px before viewport
});
images.forEach(function(img) { observer.observe(img); });
});
This method requires changing src to data-src in your image markup and providing a lightweight placeholder. The rootMargin of 200px triggers loading before the image scrolls into view, preventing visible pop-in.
When to Use IntersectionObserver
| Scenario | Native loading="lazy" |
IntersectionObserver |
|---|---|---|
| Standard product listings | Best choice | Overkill |
| Custom AJAX-loaded content | Does not work | Required |
| Animated loading effects | Not possible | Full control |
| Background images (CSS) | Not supported | Works with adaptation |
| Iframes and videos | Supported | Also works |
Method 3: Third-Party Extensions
Extensions provide admin panel configuration without code changes. Here are the main options for Magento 2:
| Extension | Price | Script Type | Key Features |
|---|---|---|---|
| Magefan Image Lazy Load | Free | Multiple JS options | Block exclusion, SEO-friendly |
| WeltPixel Lazy Load | Free | Native + JS | Product and image support, animation effects |
| Mageplaza Lazy Loading | Free | Configurable | Per-page control, multiple placeholder types |
| Amasty Lazy Load | $259 | Advanced | Preload first-screen images, threshold config |
| Plumrocket Lazy Load | Free | Native | Lightweight, minimal configuration |
Extension Installation
Install through Composer (standard for all extensions):
composer require vendor/extension-package-name
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:clean
After installation, configure the extension at Stores > Configuration > [Extension Name] > Lazy Load. Set "Enable Lazy Loading" to "Yes" and configure the threshold (distance in pixels before the viewport at which images start loading).
Comparison: Which Method to Choose
| Factor | Native HTML | IntersectionObserver | Extension |
|---|---|---|---|
| Setup complexity | Low | High | Medium |
| Cost | Free | Free (dev time) | Free to $259 |
| Performance overhead | Zero | Minimal JS | Varies by extension |
| Customization | Limited | Full control | Admin panel options |
| Browser support | All modern browsers | All modern browsers | Depends on script |
| Best for | Most stores | Custom themes | Non-technical admins |
For most Magento 2 stores, start with native loading="lazy". It has zero performance overhead, no dependencies, and works across all modern browsers. Add an extension only if you need admin-configurable thresholds, placeholder images, or iframe support.
How Server Performance Affects Image Loading
Lazy loading optimizes when images load, but the speed of each image request depends on your server infrastructure. Two stores with identical lazy loading setups will perform differently if one runs on a shared server and the other on managed Magento hosting with dedicated resources.
TTFB and CDN
Time to First Byte determines how fast your server responds to each image request. A server with high TTFB adds delay to every lazy-loaded image as the user scrolls. A Content Delivery Network serves images from edge locations close to your visitors, ensuring that when an offscreen image triggers loading, it arrives from a nearby server rather than your origin.
Image Format Optimization
Before implementing lazy loading, optimize the images themselves. Compress images and serve modern formats like WebP where possible. Lazy loading a 2 MB uncompressed PNG still creates a poor experience when the user scrolls to it.
How to Test and Verify Lazy Loading
After implementation, verify that lazy loading works and improves your scores.
Google PageSpeed Insights
Run your category page URL through PageSpeed Insights. The "Defer offscreen images" warning should disappear or show reduced savings. Check both mobile and desktop scores.
Chrome DevTools Network Tab
- Open DevTools (F12) > Network tab
- Filter by "Img" type
- Reload the page
- Scroll down and watch new image requests appear as you scroll
If images load only when you scroll near them, lazy loading works.
Lighthouse Audit
Run a Lighthouse performance audit in Chrome DevTools. Check the "Diagnostics" section for:
- "Defer offscreen images" (should pass)
- "Serve images in next-gen formats" (separate optimization)
- "Image elements have explicit width and height" (prevents CLS)
WebPageTest
For production testing, use WebPageTest with a simulated 4G connection. Compare waterfall charts before and after lazy loading. Look for a shorter initial load waterfall and image requests that appear later in the timeline.
Common Mistakes to Avoid
Lazy loading all images including above-the-fold content. This delays the LCP element and makes the page feel slower. Exclude the first row of products and any hero images.
Missing width and height attributes. Without explicit dimensions, the browser cannot reserve space for lazy-loaded images. As images load during scrolling, content shifts around, increasing your CLS score.
Using JavaScript-only solutions without a fallback. If JavaScript fails to execute, images with data-src instead of src never load. Native loading="lazy" degrades gracefully because the src attribute is always present.
Setting the threshold too low. A threshold of 0px means images load only when they enter the viewport, causing visible pop-in. Set a threshold of at least 200px so images start loading before the user scrolls to them.
FAQ
What does "Defer offscreen images" mean in Google PageSpeed Insights?
It means your page loads images that are not visible in the initial viewport. Google recommends lazy loading these images so they load only when the user scrolls near them, reducing initial page weight and improving load time.
Does Magento 2 support lazy loading natively?
Magento 2.4.x supports the native HTML loading="lazy" attribute. You can add this attribute to image tags in your theme templates without installing any extension. Some Magento themes already include this attribute by default.
Which images should I NOT lazy load?
Never lazy load your hero banner, the first product image on detail pages, category header images, or any image visible without scrolling. These are above-the-fold elements and should load immediately. Lazy loading your LCP element hurts your Core Web Vitals score.
Do I need an extension for lazy loading in Magento 2?
No. The native loading="lazy" attribute handles most use cases without an extension. Extensions add value if you need admin panel configuration, placeholder images, animated loading effects, or support for AJAX-loaded content.
How do I know if lazy loading is working on my site?
Open Chrome DevTools, go to the Network tab, filter by images, and reload your page. Scroll down and watch the network panel. If new image requests appear as you scroll, lazy loading is active.
Will lazy loading affect my SEO?
Lazy loading improves SEO by reducing page load time, which is a Google ranking factor. Googlebot renders JavaScript and recognizes the loading="lazy" attribute, so lazy-loaded images are crawled and indexed. Always include descriptive alt attributes on all images.
What is a good LCP score for a Magento store?
Google considers LCP under 2.5 seconds as "good." For Magento category pages with many images, aim for under 2 seconds. Server response time, image optimization, and lazy loading all contribute to your LCP score.
Can I use lazy loading with a CDN?
Yes. Lazy loading and CDN work together. Lazy loading controls when the browser requests an image, and the CDN ensures that request is served from the nearest edge location. This combination provides the best image loading performance.
What is the IntersectionObserver API?
IntersectionObserver is a JavaScript API that detects when an element enters or exits the browser viewport. It is more efficient than scroll event listeners and gives developers fine-grained control over when lazy-loaded images trigger their actual download.
How much can lazy loading improve my page speed?
Results depend on how many images your page contains. A category page with 40 products can see initial page weight reduced by 60 to 80%. PageSpeed Insights scores improve by 5 to 20 points for image-heavy pages.