Serve correctly sized images with srcset and sizes
Use srcset and sizes attributes with Shopify's image_tag Liquid filter to serve appropriately sized images for each viewport.
Without srcset and sizes, the browser has only one image to download regardless of the viewport. Mobile devices download desktop-sized images unnecessarily, wasting bandwidth and slowing LCP. Responsive images ensure that the browser downloads an appropriately sized image for the current viewport, reducing initial page weight and improving performance.
Anchor to How responsive images work with ,[object Object], and ,[object Object]How responsive images work with srcset and sizes
srcset and sizesThe srcset attribute provides multiple image options at different widths. The sizes attribute tells the browser which option to use based on layout.
The browser:
- Checks the current layout width.
- Evaluates the
sizesattribute to determine the image's display size in the current layout. - Checks the device's pixel density, such as 2x for Retina screens.
- Selects the smallest image from
srcsetthat fits the required size. - Downloads only that one image.
Anchor to The recommended Shopify ,[object Object], implementationThe recommended Shopify image_tag implementation
image_tag implementationShopify's image_tag Liquid filter generates responsive images with proper srcset, sizes, and dimensions:
This generates a complete responsive image with:
- A
srcsetat the specified widths. - Automatic
heightandwidthattributes, which prevent CLS. - Shopify CDN URLs with automatic format conversion.
Anchor to Common mistakesCommon mistakes
Too many widths in srcset:
- Hurts caching effectiveness.
- The browser has to evaluate more options.
- Four to six widths are usually sufficient.
- You don't need a perfectly sized image for every pixel.
Wrong sizes attribute:
- The browser downloads the wrong image.
- It might download the largest image, wasting bandwidth.
- It might download the smallest image, which looks pixelated.
- Use the Responsive Image Linter extension to check.
No sizes attribute:
- The browser defaults to downloading the largest image.
- It wastes bandwidth on mobile.
- LCP is slower.
Anchor to Getting ,[object Object], rightGetting sizes right
sizes rightThe sizes attribute is notoriously difficult. Use the Responsive Image Linter Chrome extension:
- Install the extension.
- Put any value in the
sizesattribute. - The extension calculates the correct value.
- Update your code.
Keep the srcset suggestions reasonable. You don't need a perfectly sized image for every possible width. Fewer widths improve caching.
Anchor to Let the browser work out ,[object Object], for lazy-loaded imagesLet the browser work out sizes for lazy-loaded images
sizes for lazy-loaded imagesFor images with loading="lazy", set sizes to auto instead of writing a breakpoint list. The browser uses the image's own layout width to pick a source, so the value can't drift out of sync with your CSS:
Shopify injects a polyfill for browsers that don't support sizes="auto" natively, so it's safe to use today.
auto applies only to images with loading="lazy". Eager images, including the LCP image, still need an explicit sizes value, because the browser has to pick a source before layout runs. Never lazy-load the LCP image to get auto: the lazy-loading delay costs far more than an imperfect sizes value.
auto applies only to images with loading="lazy". Eager images, including the LCP image, still need an explicit sizes value, because the browser has to pick a source before layout runs. Never lazy-load the LCP image to get auto: the lazy-loading delay costs far more than an imperfect sizes value.
Anchor to ExamplesExamples
Anchor to Special considerations for carousels, slideshows, and gridsSpecial considerations for carousels, slideshows, and grids
Components that contain many images require careful implementation to avoid hurting performance.
- Load only what's needed: Don't render
<img>tags for images that aren't visible. For a carousel, render<img>tags only for the first few images, and use JavaScript to add new<img>tags as the user navigates through the carousel. See Limit pagination depth for detailed carousel implementation patterns. - Prioritize visible images: Make sure the first, visible image in a slideshow or grid loads eagerly with
loading="eager", and hasfetchpriority="high"if it's the LCP element. All other non-visible images should useloading="lazy".
Anchor to TestingTesting
- Responsive Image Linter: A Chrome extension that helps you validate and generate correct
sizesattributes. - Performance panel, Insights tab: Run a measurement to see whether Image sizes are too large is flagged as an optimization opportunity.
- Chrome DevTools Network panel: Verify that the correctly sized image downloads at different viewport sizes.
- Device Mode: Test at different viewport sizes, such as mobile, tablet, and desktop, and compare the file sizes of images being loaded.
Anchor to ReferencesReferences
image_tagfilterimage_urlfilterproduct.featured_image- Responsive images on Shopify with Liquid
- Optimizing images for performance on Shopify
- Demo page: Liquid image_tag demo
- Prevent image layout shift
- Never lazy-load the LCP image
- Mark the LCP image with
fetchpriority="high"