Lazy Loading in 2026: What Browsers Handle Natively vs What Needs a Module
Lazy Loading in 2026: What Browsers Handle Natively vs What Needs a Module
Lazy loading is a performance optimization technique that defers the loading of off-screen resources until the user scrolls near them. In 2026, native browser support for lazy loading has matured significantly, but there are still scenarios where PrestaShop store owners need additional modules or custom implementations. This guide explains exactly what browsers handle on their own, what gaps remain, and how to implement the best lazy loading strategy for your PrestaShop store.
What Native Lazy Loading Covers in 2026
The HTML loading="lazy" attribute is now supported by over 95% of browsers worldwide. This includes Chrome (since v77), Firefox (since v75), Safari (since v15.4), Edge (since v79), and all Chromium-based browsers. This means for most visitors to your store, native lazy loading works out of the box.
How Native Lazy Loading Works
Adding loading="lazy" to an <img> or <iframe> tag tells the browser to defer loading that resource until it is within a certain distance from the viewport. The browser handles all the timing and intersection logic internally, with zero JavaScript overhead.
<!-- Native lazy loading for images -->
<img src="product-image.jpg"
loading="lazy"
width="800"
height="600"
alt="Product Name">
<!-- Native lazy loading for iframes -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
loading="lazy"
width="560"
height="315"></iframe>What Browsers Handle Natively
| Feature | Native Support | Notes |
|---|---|---|
Images (<img>) | Yes - all major browsers | Use loading="lazy" attribute |
Iframes (<iframe>) | Yes - all major browsers | Use loading="lazy" attribute |
Responsive images (<picture>) | Yes | Put loading="lazy" on the <img> inside |
| srcset images | Yes | Works with loading="lazy" on the <img> |
| Above-the-fold detection | Partial | Browsers try to detect, but not always accurate |
What Browsers Do NOT Handle
| Feature | Native Support | Solution Needed |
|---|---|---|
| CSS background images | No | IntersectionObserver API or module |
| Video elements | No | Custom JavaScript or module |
| Placeholder/blur-up effects | No | JavaScript library or module |
| Priority hints for above-fold images | Partial | fetchpriority="high" attribute |
| Dynamic/AJAX-loaded content | No | JavaScript-based lazy loading |
| Third-party widget deferral | No | Custom implementation |
Implementing Native Lazy Loading in PrestaShop
For PrestaShop 8.x and 9.x Themes
Modern PrestaShop themes (like Hummingbird for PS 9) often include native lazy loading by default. To verify or add it to your theme, edit your template files where product images are rendered.
For product listing pages, find the template that renders product thumbnails (typically themes/yourtheme/templates/catalog/_partials/miniatures/product.tpl):
{* Before - no lazy loading *}
<img src="{$product.cover.bySize.home_default.url}"
alt="{$product.name}">
{* After - with native lazy loading *}
<img src="{$product.cover.bySize.home_default.url}"
loading="lazy"
width="{$product.cover.bySize.home_default.width}"
height="{$product.cover.bySize.home_default.height}"
alt="{$product.name}">Critical Rule: Never Lazy Load Above-the-Fold Images
The most common lazy loading mistake is applying it to images that are visible without scrolling. This actually hurts performance because the browser delays loading content that the user sees immediately. Google's Core Web Vitals will penalize you for this with a higher LCP (Largest Contentful Paint) score.
Images that should NOT be lazy loaded:
- Your store logo
- Hero/banner images at the top of the page
- The first 1-2 product images on category pages
- Any image visible in the initial viewport without scrolling
For these critical images, use eager loading with priority hints:
<img src="hero-banner.jpg"
loading="eager"
fetchpriority="high"
width="1200"
height="400"
alt="Summer Sale Banner">When You Need a Module: CSS Background Images
PrestaShop themes frequently use CSS background images for sliders, banners, category headers, and promotional blocks. The loading="lazy" attribute does not work for CSS backgrounds. You need JavaScript to handle these.
IntersectionObserver Approach
// Lazy load CSS background images
document.addEventListener('DOMContentLoaded', function() {
const lazyBackgrounds = document.querySelectorAll('[data-bg]');
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const el = entry.target;
el.style.backgroundImage = 'url(' + el.dataset.bg + ')';
el.classList.add('bg-loaded');
observer.unobserve(el);
}
});
}, {
rootMargin: '200px 0px'
});
lazyBackgrounds.forEach(function(bg) {
observer.observe(bg);
});
});In your HTML/Smarty template:
{* Instead of inline background-image *}
<div class="category-banner" data-bg="{$category_image_url}"></div>When You Need a Module: Placeholder Effects
Native lazy loading shows nothing until the image loads, which can cause a jarring visual experience. Modules or libraries can add:
- Blur-up effect (LQIP) - Load a tiny, blurred version first, then replace with the full image. Creates a smooth perceived loading experience.
- Skeleton screens - Gray placeholder blocks that match the image dimensions, giving the user a sense of the page layout before images load.
- Dominant color placeholders - Extract the dominant color from the image and use it as the placeholder background. Pinterest popularized this approach.
When You Need a Module: Video Lazy Loading
Product videos and embedded YouTube/Vimeo players should be lazy loaded but cannot use the native attribute (except for iframes). For HTML5 <video> elements:
// Lazy load video elements
const lazyVideos = document.querySelectorAll('video[data-src]');
const videoObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const video = entry.target;
video.src = video.dataset.src;
video.load();
videoObserver.unobserve(video);
}
});
});
lazyVideos.forEach(function(video) {
videoObserver.observe(video);
});Impact on PrestaShop Performance and Core Web Vitals
Proper lazy loading directly impacts three Core Web Vitals metrics:
- LCP (Largest Contentful Paint) - Lazy loading above-the-fold images HURTS LCP. Only lazy load below-the-fold images.
- CLS (Cumulative Layout Shift) - Images without width/height attributes cause layout shifts when they load. Always specify dimensions.
- INP (Interaction to Next Paint) - Fewer resources loading simultaneously means the main thread is less congested, improving interactivity.
Must-Have: Width and Height Attributes
Without explicit width and height attributes, the browser does not know how much space to reserve for a lazy-loaded image. When the image finally loads, the page layout shifts, causing a high CLS score.
<!-- BAD - causes layout shift -->
<img src="product.jpg" loading="lazy" alt="Product">
<!-- GOOD - reserves space, no layout shift -->
<img src="product.jpg" loading="lazy"
width="400" height="400" alt="Product">
<!-- ALSO GOOD - CSS aspect-ratio -->
<img src="product.jpg" loading="lazy"
style="aspect-ratio: 1/1; width: 100%;" alt="Product">PrestaShop-Specific Lazy Loading Recommendations
Product Listing Pages (Category Pages)
Lazy load all product images except the first row (typically 3-4 products visible above the fold). Use native loading="lazy" for product images and apply fetchpriority="high" to the first row.
Product Detail Pages
The main product image should be loaded eagerly with fetchpriority="high". Thumbnail images in the gallery can be lazy loaded. Related/cross-sell product images at the bottom should be lazy loaded.
Homepage
Slider/carousel images above the fold should be eager loaded (at minimum the first slide). Module blocks below the fold (featured products, new products, etc.) should use lazy loading.
CMS Pages
Images embedded in CMS content are the hardest to optimize because they are typically stored as raw HTML in the database. A module or custom JavaScript is needed to add loading="lazy" to images within CMS content.
Quick Implementation Checklist
- Add
loading="lazy"to all<img>tags below the fold in your theme templates - Add
widthandheightattributes to ALL images (lazy or not) - Use
loading="eager"andfetchpriority="high"on above-the-fold hero images and the first row of products - If your theme uses CSS background images for sliders/banners, implement IntersectionObserver-based lazy loading
- Test with Google PageSpeed Insights to verify LCP and CLS improvements
- Test with real devices on slow connections (Chrome DevTools throttling) to ensure images load before users scroll to them
Summary: Module vs. Native
| Scenario | Solution |
|---|---|
| Standard product images | Native loading="lazy" - no module needed |
| CSS background images | Module or custom JS with IntersectionObserver |
| Blur-up / LQIP placeholders | Module or JS library (lazysizes, lozad) |
| Video lazy loading (HTML5) | Custom JS with IntersectionObserver |
| YouTube/Vimeo embeds | Native loading="lazy" on iframe - no module |
| CMS content images | Module to auto-add loading attribute to stored HTML |
| Third-party widget deferral | Custom JS implementation |
For more details, read our guides: PrestaShop Image Optimization: Alt Tags, Lazy Loading and Page Speed and Page Speed and SEO: How Slow Loading Kills Your Google Rankings.
Was this answer helpful?
Still have questions?
Can't find what you're looking for? Send us your question and we'll get back to you quickly.