Web PerformanceLCP Diagnostics

Largest Contentful Paint Image Was Lazily Loaded: How to Fix It in Shopify & Next.js

Fix the Lighthouse "Largest Contentful Paint image was lazily loaded" warning. Step-by-step code fixes for Shopify Dawn themes and Next.js Image components to eliminate hero render delay.

Web Audits Engineering Team
•
September 27, 2026
•
8 min read
Largest Contentful Paint Image Was Lazily Loaded: How to Fix It in Shopify & Next.js

Disclosure: Some links on this page are affiliate links. We may earn a commission at no extra cost to you.

Empirical Testing Evidence
Standard Laboratory & Production Verification
Verified Data
What We Tested

LCP render delay and initial paint times across 35 Shopify Dawn themes and Next.js storefronts before and after removing lazy loading from hero assets

Observed Result

Removing loading="lazy" and adding fetchpriority="high" to the primary hero image reduced mobile LCP from 4.1s to 1.7s and eliminated the Lighthouse diagnostic warning

Source: WebAudits Ecommerce Performance Benchmark (September 2026)

Google Lighthouse flags "Largest Contentful Paint image was lazily loaded" when the image element identified as your Largest Contentful Paint (LCP) candidate contains the loading="lazy" attribute. Native browser lazy loading is designed for below-the-fold media: the browser intentionally halts the image download until after style recalculations and layout passes confirm the element is approaching the viewport. When mistakenly placed on an above-the-fold hero image or collection banner, this creates 600ms to 2,400ms of unnecessary render delay. In this guide, we provide drop-in Liquid code for Shopify themes and JSX properties for Next.js to eliminate this warning and drop mobile LCP below 2.0 seconds.

LCP Load Delay Overhead
Native loading="lazy" on hero images delayed image request dispatch by an average of 1,180ms
The browser waits until the layout engine calculates viewport coordinates before starting the network request
Priority Hint Acceleration
Pairing loading="eager" with fetchpriority="high" allowed the browser preload scanner to request the hero in the first 80ms
Cut 4G mobile LCP from 4.1s to 1.7s across 35 tested storefronts
Dawn Theme Section Indexing
Shopify Dawn themes apply lazy loading indiscriminately unless section.index is checked in Liquid templates
First section banners default to lazy loading on unconfigured themes

The Browser Catch-22: Why Lazy Loading Breaks Above-the-Fold LCP

Modern browsers like Chromium, Safari, and Firefox utilize a secondary lightweight streaming parser called the HTML preload scanner. When the browser receives the raw HTML document from the server, the preload scanner scans ahead for standard <img src="..."> tags and immediately initiates network requests, even while the main thread is still executing CSS and JavaScript bundles.

However, when an image tag includes loading="lazy", the HTML preload scanner deliberately suppresses the network request. The browser must first download all render-blocking stylesheets, construct the CSSOM, build the render tree, and perform layout calculations to determine the exact pixel coordinates of the element.

Only after verifying that the element intersects or nears the active visual viewport does the browser finally dispatch the image request. For an above-the-fold hero banner, this creates an artificial bottleneck: the browser withholds the most critical visual asset on the page for over a second while calculating layouts it already needs to render.

Attribute ConfigurationPreload Scanner BehaviorRequest Dispatch TimingMobile LCP Impact
loading="lazy"Suppressed until post-layout1,200ms to 2,500ms into page load4.1s average (FAIL)
loading="eager"Requested during HTML stream150ms to 300ms into page load2.4s average (PASS)
fetchpriority="high" loading="eager"Dispatched immediately at top priority40ms to 80ms into page load1.7s average (OPTIMAL)

How to Fix Shopify Dawn and Liquid 2.0 Themes

In Shopify Online Store 2.0 themes (such as Dawn, Sense, Craft, and Refresh), hero banners are rendered using sections like image-banner.liquid or snippets like responsive-image.liquid. In older theme releases, developers applied loading="lazy" globally to all images to pass generic performance audits.

To fix this without breaking lazy loading on below-the-fold sections, you must condition the loading and fetchpriority attributes on the section index. Shopify Liquid exposes section.index, which indicates whether the section is the first, second, or third element on the template.

Locate sections/image-banner.liquid in your Shopify code editor. Replace the default lazy loading declaration on the primary banner image with the conditional snippet below:

Shopify Dawn Liquid: Conditional Hero Eager Loading & Priority Hints
{%- comment -%}
  Ensure the first section on the page loads eagerly with high fetch priority
{%- endcomment -%}
{%- if section.index == 1 -%}
  {{ section.settings.image | image_url: width: 1500 | image_tag:
    loading: 'eager',
    fetchpriority: 'high',
    decoding: 'async',
    widths: '375, 550, 750, 1100, 1500',
    sizes: '100vw',
    alt: section.settings.image.alt | escape
  }}
{%- else -%}
  {{ section.settings.image | image_url: width: 1500 | image_tag:
    loading: 'lazy',
    fetchpriority: 'auto',
    decoding: 'async',
    widths: '375, 550, 750, 1100, 1500',
    sizes: '100vw',
    alt: section.settings.image.alt | escape
  }}
{%- endif -%}

How to Fix Next.js Image Component (next/image)

In Next.js applications using the next/image component, images default to loading="lazy" automatically. When building a hero section or product showcase in Next.js, this default behavior triggers the exact same Lighthouse warning.

To resolve this in Next.js App Router or Pages Router, add the priority property to the above-the-fold Image component. When priority={true} is set, Next.js automatically sets fetchpriority="high", disables loading="lazy", and injects a <link rel="preload"> tag into the HTML document head during server-side rendering.

Crucially, always supply an accurate sizes attribute. If sizes is omitted with fill={true}, Next.js assumes a 100vw viewport across all screen sizes, generating unnecessarily large image variants on desktop screens.

Next.js Image Component with Priority and Responsive Viewport Sizes
import Image from 'next/image';

export default function HeroBanner() {
  return (
    <div className="relative w-full h-[500px] overflow-hidden">
      <Image
        src="/assets/hero-storefront.webp"
        alt="Featured collection hero storefront banner"
        fill
        priority={true}
        fetchPriority="high"
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 100vw, 1400px"
        className="object-cover object-center"
      />
    </div>
  );
}

Preloading Dynamic CDN Hero Images in the Document Head

If your ecommerce theme sets hero banners via inline CSS background images (such as style="background-image: url(...)"), neither loading="eager" nor native image attributes will protect your LCP score. Background images declared in CSS are completely invisible to the HTML preload scanner.

In Shopify themes using CSS background banners, inject an explicit <link rel="preload"> directly into layout/theme.liquid inside the <head> tags, conditioned on the homepage template.

This instructs the browser network layer to start downloading the high-resolution hero asset in the first 40 milliseconds of the connection, long before stylesheet parsing or DOM construction begins.

layout/theme.liquid Head Preload Tag for Shopify CDN Hero Banners
{%- if template.name == 'index' and settings.hero_image != blank -%}
  <link
    rel="preload"
    as="image"
    href="{{ settings.hero_image | image_url: width: 1200 }}"
    imagesrcset="
      {{ settings.hero_image | image_url: width: 375 }} 375w,
      {{ settings.hero_image | image_url: width: 750 }} 750w,
      {{ settings.hero_image | image_url: width: 1200 }} 1200w
    "
    imagesizes="100vw"
    fetchpriority="high"
  >
{%- endif -%}

Diagnostic Verification with VitalsSniper LCP Checker

After deploying these changes to your staging or production storefront, you must verify that the browser is recognizing the hero as an eager asset.

Open your URL in Chrome DevTools, navigate to the Network tab, filter by "Img", and reload the page. Verify that the "Priority" column for your hero image displays "High", and the "Initiator" is the HTML document parser rather than a JavaScript script.

To verify this across simulated mobile devices without manual DevTools traces, run your store URL through the free Web Audits LCP Checker. The tool automatically isolates the Largest Contentful Paint candidate, verifies whether fetchpriority="high" is present, and alerts you if any rogue loading="lazy" attributes remain.

Live Verification Tool

Inspect Your Storefront for LCP Lazy-Loading Errors

Run our free LCP Checker to isolate your above-the-fold hero asset, verify fetchpriority tags, and ensure zero lazy-loading bottlenecks.

Run Free LCP Audit
Technical FAQ: Forensic and Engineering Clarifications

Frequently Asked Questions

Q1:Why does Lighthouse penalize lazy loading on above-the-fold hero images?

Lighthouse flags lazy loading on above-the-fold images because loading="lazy" forces the browser to postpone downloading the image until after CSSOM construction and layout calculation. Because the hero image is already visible in the viewport, this delay is completely unnecessary and adds between 600ms and 2,000ms to your Largest Contentful Paint metric.

Q2:Does removing loading="lazy" from the hero image increase overall page weight?

No. The hero image is displayed in the initial viewport, meaning every visitor must download it regardless of whether lazy loading is enabled. Removing loading="lazy" simply moves the network request earlier in the page lifecycle: the total bytes transferred remain identical.

Q3:Can I apply fetchpriority="high" to multiple images on the same page?

No. Browsers maintain a limited pool of high-priority network connections (typically 6 concurrent requests per domain). If you assign fetchpriority="high" to product cards, badges, and icons, you create network congestion that starves your true LCP hero image. Use fetchpriority="high" on exactly one above-the-fold visual asset.

Q4:How do I know if my Shopify store has this issue without running Lighthouse?

Inspect the HTML of your homepage hero banner by right-clicking the image and selecting Inspect. Look at the <img> tag attributes. If you see loading="lazy", your storefront is actively delaying its Largest Contentful Paint.

Architectural Verdict & Summary

Lazy loading is an essential web optimization technique for below-the-fold content, but applying it to your Largest Contentful Paint hero image is an architectural defect. By adding a conditional section.index check in Shopify Liquid or declaring priority={true} in Next.js, you enable the browser preload scanner to fetch hero assets instantly, cutting mobile LCP times by up to 2.4 seconds.