Shopify CLS Fix — Every Image Needs Explicit width and height Attributes
Cumulative Layout Shift (CLS) measures how much page content moves unexpectedly during loading. The most common cause in Shopify themes is images without explicit width and height attributes. When a browser encounters an img tag without these attributes, it cannot reserve the correct amount of space before the image loads — so when the image arrives, everything below it shifts down. A single hero image without dimensions can push your CLS score from 0 to 0.25+ (the 'Poor' threshold is 0.1). The fix is one attribute change.
Why missing width and height causes CLS
Modern browsers use the intrinsic width and height attributes of an image to calculate its aspect ratio before the image downloads. With this information, the browser reserves exactly the right amount of space in the layout, and when the image loads it fills that space without shifting anything. Without these attributes, the browser allocates zero height for the image initially. When the image loads, it expands to its full height, pushing all subsequent content down — that's a layout shift. The fix is providing the dimensions so the browser can pre-allocate space.
How image_tag adds width and height automatically
The Shopify image_tag filter automatically adds width and height attributes that match the image's intrinsic dimensions: {{ product.featured_image | image_url: width: 800 | image_tag }}. The generated markup includes width="800" and height="533" (calculated from the image's aspect ratio). These attributes tell the browser to reserve 533px of vertical space for this image before it loads, preventing layout shift. This is one of the key reasons to migrate from manual img tags to image_tag.
Adding width and height to manual img tags
If you build img tags manually rather than using image_tag, add the attributes explicitly: <img src="{{ image | image_url: width: 800 }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.alt }}">. Note: use the image object's .width and .height properties, not hardcoded values — the intrinsic dimensions vary by image. For responsive images where CSS sets a different display size, the width and height attributes still prevent CLS because the browser uses them to calculate the aspect ratio, not as the final display dimensions.
Auditing your theme for missing dimensions
Run a PageSpeed Insights audit on your homepage. The 'Image elements do not have explicit width and height' audit in the Opportunities section lists every image missing these attributes. You can also search your theme's Liquid files for '<img' and check whether each is followed by width= and height= attributes. Images generated with image_tag are automatically compliant — manual img tags require manual attribute addition.
The fix: before and after
// CODE_COMPARISON
Frequently asked questions
- Do I need to use the exact display dimensions for width and height?
No. The browser uses the width and height HTML attributes to calculate the image's intrinsic aspect ratio, not as the final display size. CSS controls the actual display dimensions. You should use the image's natural dimensions (image.width, image.height) as attributes, and CSS to make it responsive — the browser will then reserve the correct aspect-ratio-based space regardless of the display size.
- What CLS improvement can I expect from adding width and height?
For a typical Shopify homepage with a hero image, product grid, and collection banners all missing dimensions, fixing the width and height attributes can reduce CLS from 0.15-0.4 (Poor) to under 0.1 (Good). The improvement is most dramatic on slow connections where images load late relative to the rest of the page content.
- Does the CSS aspect-ratio property replace width and height attributes?
CSS aspect-ratio can also prevent CLS, but HTML width and height attributes are simpler, more broadly supported (back to IE), and the recommended approach by Google. The image_tag filter handles this automatically. Use CSS aspect-ratio only in cases where you need to reserve space for an image that does not have known dimensions — for example, a dynamically sized container.
// SCAN_YOUR_CODE
Does your theme have this bug?
Paste your code. Syphio automatically detects and fixes this error and hundreds of others — in seconds.
Validate my Liquid →