Lazy loading has a reputation as an easy, free performance win, add loading="lazy" to your images, watch your page weight drop, done. For a lot of below-the-fold content, that reputation is deserved. But applied to the wrong image, lazy loading does the opposite of what merchants expect: it can directly damage your Largest Contentful Paint score and slow down the exact moment a shopper first sees your product.
This is a narrower topic than most “speed up your Shopify store” advice, and it’s worth treating as its own decision rather than a blanket setting. This post covers what native lazy loading actually does on Shopify themes, why it helps in some spots and actively hurts in others, and how to work out which of your images should have it and which shouldn’t.
The Short Answer
Lazy loading below-the-fold images, product grids further down a collection page, related products, footer content, is almost always a good idea on Shopify. Lazy loading your above-the-fold hero image, or the first product image on a product page, is almost always a bad idea, because that image is frequently the Largest Contentful Paint (LCP) element Google measures, and lazy loading delays the browser from starting to fetch it. Get this split right and you get faster pages without hurting your Core Web Vitals. Get it backwards and you can make your homepage load slower while thinking you’ve sped it up.
How Native Lazy Loading Works on Shopify
Modern Shopify themes built on Online Store 2.0 (Dawn and its descendants, along with most current third-party themes) use the browser-native loading="lazy" attribute on <img> tags, generated through Liquid’s image rendering, typically via the image_url filter combined with responsive srcset markup, or the image_tag filter which can set the loading attribute directly. This is different from the older JavaScript-based lazy loading libraries many themes relied on before browsers supported it natively; native lazy loading is lighter, doesn’t depend on a JS library loading first, and is what Google’s own Lighthouse tooling expects to see.
When an image has loading="lazy", the browser defers fetching it until it’s getting close to entering the viewport, roughly a few screen-heights away, though the exact threshold varies by browser. When an image is left as loading="eager" (the default if no attribute is set) or has no loading attribute at all, the browser fetches it immediately as the page parses, regardless of where it sits on the page.
The theme decides this for you at the section and snippet level. Whether your hero banner, product image, or a specific app block gets lazy loading applied depends on how that block’s Liquid code renders the image tag, which means two stores on the same theme can behave differently if one has customised sections or added apps that inject their own image markup.
Why This Directly Affects Core Web Vitals
Largest Contentful Paint measures the time it takes for the largest visible content element, very often an image, to render on screen. Google uses LCP as one of the Core Web Vitals it reports in Search Console and factors into its page experience signals.
Here’s the mechanic that catches merchants out: when an image has loading="lazy", the browser doesn’t just delay displaying it, it delays discovering it. The browser has to parse further into the HTML and get closer to the image’s position before it even issues the network request for that file. If that lazily-loaded image happens to be your LCP candidate, which a full-width hero banner or the primary product photo usually is, you’ve added delay to the exact metric Google is measuring, even though the rest of the page might genuinely be loading faster.
This is the opposite of the effect merchants expect. The intuition “lazy loading makes pages faster” is true for total page weight and for images the visitor may never scroll to. It’s not true for the one image that defines how fast the page feels to load, because that’s specifically the image the visitor sees first.
The Trade-Off: Above-the-Fold vs Below-the-Fold
This is the core distinction the whole topic comes down to.
Above-the-fold images (turn lazy loading off):
– Homepage hero banners and the first slide of any carousel
– The primary product image on a product page (the one visible without scrolling)
– Any image inside your header or the first visible section
These should be set to loading="eager", and for genuinely critical LCP candidates, ideally paired with fetchpriority="high" so the browser prioritises fetching that file over less important requests competing for bandwidth at the same time. Some themes also support preloading the LCP image via a <link rel="preload"> tag in the document head, which tells the browser about the image before it even reaches that point in the HTML.
Below-the-fold images (lazy loading is correct):
– Product grids on collection pages beyond the first visible row
– Related products, “you may also like” sections
– Footer content, blog post thumbnails on index pages
– Any image a visitor only sees after scrolling
For these, lazy loading reduces the number of images fetched on initial page load, which lowers total data transferred and frees up bandwidth and connection slots for the resources that actually matter for the initial render. On a throttled mobile connection, which is how most Australian shoppers are browsing, and how Google’s Lighthouse mobile test simulates the experience, this genuinely helps both load speed and data usage.
Where Shopify Stores Get This Wrong
A few recurring patterns show up when we review real Shopify stores:
Image optimisation or “speed” apps applying lazy loading indiscriminately. Several third-party apps designed to improve performance add loading="lazy" to every image on the page as a blanket setting, without excluding the hero or LCP candidate. This is the single most common cause of a store’s LCP score getting worse after installing a “speed” app, not better.
Carousel and slider apps loading every slide eagerly. This is the inverse problem, some carousel implementations fetch every slide’s image immediately regardless of position, which is wasteful for slides two through five that most visitors never see, and can itself compete for bandwidth with the actual LCP element on slide one.
Theme customisations that strip the loading attribute during a redesign. When a section is rebuilt or a new app block is added, it’s easy for whoever built it to write a plain <img> tag without setting the loading attribute at all, which defaults to eager, fine for a hero, wasteful for a grid of twenty products further down the page.
No distinction between the first and subsequent images in a gallery. Product pages with an image gallery or thumbnail strip should generally eager-load the main displayed image and lazy-load the rest of the gallery, not treat the whole gallery as one block.
A Practical Checklist for Auditing Your Store
- Identify your LCP element on your homepage, a representative collection page, and a representative product page using PageSpeed Insights or Chrome DevTools’ Performance panel, it will name the specific element.
- View the page source or use DevTools to inspect that element’s
<img>tag and check whether it hasloading="lazy"set. - If it does, that’s your fix, remove the lazy attribute (or set it to
eager) for that specific image, ideally by adjusting the theme section or snippet rather than a one-off manual edit that will be overwritten on the next theme update. - Check whether a
fetchpriority="high"hint or a preload tag is warranted for that same element, particularly if it’s a large hero image competing with other early page requests. - Scroll down and confirm below-the-fold images do have
loading="lazy"set, if a “speed” app or a recent theme customisation stripped it, you’re carrying unnecessary initial page weight. - Re-test after changes and compare both the lab score and, over the following weeks, the field data (real user Core Web Vitals) in Google Search Console, since lab tests and real-world results don’t always move in lockstep.
- Repeat the audit after installing any new app that touches images, carousels, upsell widgets, and image optimisation apps are the most common source of regressions here.
When to Bring In a Specialist
Getting the loading attribute right on one image is simple. Getting it right consistently across every template, every theme update, and every app you add over time is where this quietly breaks again without anyone noticing, because a regression here doesn’t throw an error, it just shows up as a slowly worsening Core Web Vitals trend in Search Console months later. If you want this checked properly across your actual templates rather than guessed at, our Shopify performance optimisation service audits exactly this kind of image loading behaviour alongside the other factors that affect real-world speed, so fixes hold up after the next theme change rather than needing to be redone.
FAQ
Should I just turn off lazy loading everywhere to be safe?
No, that fixes the LCP risk but reintroduces the problem lazy loading solves, loading every image on a long collection page immediately, which increases total page weight and can slow down initial render for a different reason. The fix is applying it selectively, not removing it entirely.
Does Shopify handle lazy loading automatically, or do I need to configure it?
Current Online Store 2.0 themes generally handle this reasonably well by default for standard sections, but customisations, added apps, and older or heavily modified themes frequently don’t get it right, particularly for hero sections and app-injected image blocks. Don’t assume it’s correct without checking.
How do I know if lazy loading is actually hurting my LCP score?
Run PageSpeed Insights or Lighthouse on the specific page, check which element is flagged as the LCP candidate, and inspect that element’s HTML for a loading="lazy" attribute. If your LCP element has it, that’s very likely contributing to your score.
Does this affect mobile and desktop scores differently?
Yes. Because mobile testing simulates a slower connection and CPU, any delay introduced by incorrectly lazy-loading the LCP image tends to show up more severely in mobile scores than desktop, which is worth knowing if your mobile Core Web Vitals in Search Console look worse than desktop.
Will fixing lazy loading alone get my Core Web Vitals to pass?
It’s one contributing factor, not a complete fix on its own. LCP is also affected by server response time, render-blocking CSS and fonts, and overall page weight, so treat this as one item in a broader performance review rather than the single lever that solves Core Web Vitals.
Next Step
If you’re not sure whether your hero images and product photos are quietly working against your Core Web Vitals, a Shopify audit will show you exactly which images are lazy-loaded, which aren’t, and which of those settings are actually costing you speed rather than saving it.