Lazy Loading in 2026: What Browsers Handle Natively vs What Needs a Module

415 views

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

FeatureNative SupportNotes
Images (<img>)Yes - all major browsersUse loading="lazy" attribute
Iframes (<iframe>)Yes - all major browsersUse loading="lazy" attribute
Responsive images (<picture>)YesPut loading="lazy" on the <img> inside
srcset imagesYesWorks with loading="lazy" on the <img>
Above-the-fold detectionPartialBrowsers try to detect, but not always accurate

What Browsers Do NOT Handle

FeatureNative SupportSolution Needed
CSS background imagesNoIntersectionObserver API or module
Video elementsNoCustom JavaScript or module
Placeholder/blur-up effectsNoJavaScript library or module
Priority hints for above-fold imagesPartialfetchpriority="high" attribute
Dynamic/AJAX-loaded contentNoJavaScript-based lazy loading
Third-party widget deferralNoCustom 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

  1. Add loading="lazy" to all <img> tags below the fold in your theme templates
  2. Add width and height attributes to ALL images (lazy or not)
  3. Use loading="eager" and fetchpriority="high" on above-the-fold hero images and the first row of products
  4. If your theme uses CSS background images for sliders/banners, implement IntersectionObserver-based lazy loading
  5. Test with Google PageSpeed Insights to verify LCP and CLS improvements
  6. Test with real devices on slow connections (Chrome DevTools throttling) to ensure images load before users scroll to them

Summary: Module vs. Native

ScenarioSolution
Standard product imagesNative loading="lazy" - no module needed
CSS background imagesModule or custom JS with IntersectionObserver
Blur-up / LQIP placeholdersModule or JS library (lazysizes, lozad)
Video lazy loading (HTML5)Custom JS with IntersectionObserver
YouTube/Vimeo embedsNative loading="lazy" on iframe - no module
CMS content imagesModule to auto-add loading attribute to stored HTML
Third-party widget deferralCustom 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.

Loading...
Back to top