← Back to guides
SpeedTheme DevelopmentPerformance · Published 2024-05-18 · 2 min read

Shopify Image Optimization Guide

Stop slowing down your storefronts. Learn the modern, optimal ways to render responsive images using Liquid.

Share with Shopify developers — useful guides spread faster in theme dev communities.

Why image Liquid matters

Heavy or wrongly loaded images dominate mobile performance audits. Shopify's CDN handles resizing and modern formats when you use image_url and image_tag—not hardcoded asset URLs or the deprecated img_url filter.

image_url: sized CDN URLs

{% if section.settings.image != blank %}
  {{ section.settings.image | image_url: width: 800 }}
{% endif %}

During theme customization, this issue often appears when image_picker settings are blank—always guard before calling filters.

image_tag: srcset, width, height, loading

{{ section.settings.image
  | image_url: width: 1200
  | image_tag:
    loading: 'lazy',
    width: section.settings.image.width,
    height: section.settings.image.height,
    sizes: '(min-width: 990px) 50vw, 100vw',
    alt: section.settings.image.alt | escape
}}

Explicit width and height on the tag reserve space and reduce cumulative layout shift (CLS). Pair with a sizes attribute so the browser picks an appropriate file from the generated srcset.

Loading strategy

  • Hero / LCP image: loading: 'eager'—not lazy
  • Product grids and below-fold bands: loading: 'lazy'
  • Cap widths in sliders—do not request 4000px for thumbnails

Common mistakes

  • Leaving img_url in legacy snippets
  • CSS background-image instead of theme-native image_tag
  • Missing sizes—browser downloads oversized files
  • Empty alt attributes on decorative vs informative images

Takeaway

Replace deprecated filters, guard blanks, size intentionally, and split eager vs lazy by viewport position. Broader launch checks: Theme Performance Tips.

LCP and hero images on production stores

The largest contentful paint image is almost always the homepage or collection hero. Use image_tag with explicit width, loading: 'eager', and fetchpriority: 'high' where supported—not lazy loading on the hero. Below-the-fold product grids use loading: 'lazy'.

Section settings vs product images

{% if section.settings.image != blank %}
  {{ section.settings.image
    | image_url: width: 1600
    | image_tag:
      loading: 'lazy',
      sizes: '(min-width: 990px) 50vw, 100vw',
      alt: section.settings.image.alt | escape
  }}
{% endif %}

Always guard blank image_picker values—merchants save sections before uploading assets.

Mistakes we still audit on rescue themes

  • Deprecated img_url filter still in snippets
  • Full-resolution PNG heroes on mobile PDP filmstrips
  • Missing sizes on responsive images—browser downloads oversized files
  • Background images in CSS instead of theme-native image_tag patterns

Performance checklist

  1. Replace all img_url with image_url
  2. Cap block image widths in sliders
  3. Lazy-load below-fold grids
  4. Test Lighthouse mobile on staging with apps enabled

Broader launch gates: performance checklist before launch and theme performance tips.

Topic cluster

Theme Development

Dawn, performance, images, and production theme workflows.

Convert HTML to Shopify Liquid

Paste HTML & generate Liquid with schema, blocks, and scoped CSS. No signup required.

Share

Share this guide

Found this guide useful? Share it with other Shopify developers on LinkedIn, X, or Reddit.