Key takeaways
- Most modern Shopify themes (Dawn, Craft, Sense) include
loading="lazy"on images by default.- To check: right-click any image on your store → Inspect → look for
loading="lazy"in the HTML.- Your hero/banner image should NOT be lazy loaded — it’s the Largest Contentful Paint element and must load immediately.
- To add lazy loading manually: edit image tags in section or snippet Liquid files to include
loading="lazy".
Lazy loading delays the loading of images until they’re about to enter the viewport. Instead of downloading every image on a page when it first loads, the browser only downloads images as the visitor scrolls down to them. For long Shopify product or collection pages with dozens of images, this can dramatically reduce initial page load time.
How to lazy load images in Shopify
Step 1 — Check if your theme already does it.
Right-click any image on your storefront → Inspect → look at the <img> tag in the HTML. If you see loading="lazy", your theme already includes lazy loading for that image.
Modern Shopify themes built on Dawn (the official Shopify theme) include loading="lazy" by default for:
- Collection page product images
- Gallery images below the fold
- Blog post featured images
- Section images that aren’t the first visible content
If your theme was built after 2021, it very likely includes this already.
How to add lazy loading to images manually
If your theme doesn’t include loading="lazy", add it to the image tags in your section and snippet Liquid files.
Step 1 - Duplicate your theme.
Step 2 - In the code editor, find the section or snippet where the image is rendered. Common locations:
sections/main-collection-product-grid.liquid— collection page product imagessections/featured-collection.liquid— homepage featured productssnippets/card-product.liquid— product card template used across multiple sections
Step 3 - Find the <img> tag and add loading="lazy":
<!-- Before -->
<img
src="{{ product.featured_image | img_url: '400x' }}"
alt="{{ product.featured_image.alt }}"
width="400"
height="400"
/>
<!-- After -->
<img
src="{{ product.featured_image | img_url: '400x' }}"
alt="{{ product.featured_image.alt }}"
width="400"
height="400"
loading="lazy"
/>
Step 4 - Save and test. Use Chrome DevTools Network tab to confirm images are loading only as you scroll.
How to add lazy loading in Shopify using Shopify’s image_tag filter
The modern Shopify way to render images is using the image_tag filter, which handles lazy loading (and other best practices) automatically:
{{ product.featured_image | image_url: width: 400 | image_tag: loading: 'lazy', alt: product.featured_image.alt }}
This generates an <img> tag with lazy loading, proper width/height attributes, and srcset for responsive images. If your theme is using older img_url syntax, updating to image_url + image_tag is the cleaner upgrade.
Which images should NOT be lazy loaded
The hero image / banner image. This is typically the Largest Contentful Paint (LCP) element — the largest visible image when the page first loads. LCP is a Core Web Vital that directly affects your Google ranking.
Lazy loading your hero image means the browser waits to download it until it “needs” to — but it needs it immediately. This hurts your LCP score significantly.
If your hero image has loading="lazy" in your theme, remove it. Add loading="eager" or fetchpriority="high" instead:
<img
src="banner.jpg"
alt="Summer sale banner"
loading="eager"
fetchpriority="high"
/>
fetchpriority="high" tells the browser to prioritize fetching this image over everything else — the most effective way to improve LCP.
The first product image on collection pages. If your collection page shows product images in a grid, the first row of images is visible immediately. These should not be lazy loaded. Only the images below the fold benefit from lazy loading.
Some themes handle this with conditional logic — only applying loading="lazy" to images after the first few cards.
Impact on Core Web Vitals
Lazy loading correctly implemented improves:
- LCP (Largest Contentful Paint) — by ensuring the hero image loads fast (not lazy loaded) and other resources aren’t competing for bandwidth
- TBT (Total Blocking Time) — by reducing the number of large image downloads happening during page load
It should not significantly change:
- CLS (Cumulative Layout Shift) — ensure images have explicit width and height attributes to reserve space. Without these, lazy-loaded images can cause layout shift when they load.
Using srcset for responsive images
Alongside lazy loading, srcset ensures browsers download only the image size appropriate for their screen — not a 2000px image for a 400px product card.
Shopify’s image_tag filter generates srcset automatically. For older img_url usage:
<img
src="{{ product.featured_image | img_url: '400x' }}"
srcset="{{ product.featured_image | img_url: '400x' }} 400w,
{{ product.featured_image | img_url: '800x' }} 800w,
{{ product.featured_image | img_url: '1200x' }} 1200w"
sizes="(max-width: 767px) 100vw, 50vw"
loading="lazy"
alt="{{ product.featured_image.alt }}"
/>
Combined with lazy loading, proper srcset can reduce image data transferred by 40-60% on mobile.
Is lazy loading only for images in Shopify?
No. Lazy loading applies to videos too. Shopify themes can lazy load <video> elements using the loading="lazy" attribute and preload="none", and YouTube/Vimeo embeds can be lazy loaded using a facade pattern (showing a static thumbnail until the user clicks play). For a full walkthrough, see our guide on how to lazy load videos in Shopify. Similarly, iframes (used for embedded maps or forms) can be deferred with loading="lazy". Images remain the highest-impact target since they’re the most common heavy asset on Shopify product and collection pages.