No explicit width/height high
Image elements do not have explicit width and height
Images shipped without width and height attributes give the browser no box to reserve, so layout jumps as each one loads.
What you see
Image elements do not have explicit width and height Set an explicit width and height on image elements to reduce layout shifts and improve CLS. <img src="hero.jpg"> — no width/height
What’s actually happening
Text and buttons jump down the page a beat after it opens, usually right as the hero or product photos finish downloading. Lighthouse flags it under the CLS section and lists every offending <img>. On a slow connection the jump is violent — people tap the wrong thing because the target moved under their finger. The Performance panel in Chrome DevTools shows the shift events stacking up in the Experience track.
Common causes
- <img> tags written without width and height attributes, so the browser can't compute the box until the bytes arrive
- CSS that sets width: 100% but never sets height or aspect-ratio, leaving the height to collapse to zero until load
- A CMS or page builder (WordPress, Webflow, Shopify sections) that strips dimensions or outputs responsive images without them
- Lazy-loaded images injected by JavaScript after first paint, pushing everything below them down
- Background-image swaps via JS where the container has no reserved height
How to fix it
- Put width and height attributes back on every imgAdd the image's intrinsic pixel dimensions: <img src="hero.jpg" width="1280" height="720">. Modern browsers read those two numbers, compute the aspect ratio, and reserve the box before a single byte of the image loads. The CSS can still scale it fluidly — height: auto in your stylesheet keeps it responsive while the attributes hold the space.
- Set aspect-ratio in CSS where you can't set attributesFor images you can't easily edit the markup on (some CMS outputs, CSS background images), give the container aspect-ratio: 16 / 9 or whatever matches. The browser reserves height from the ratio. Pair it with width: 100%; height: auto so it scales.
- Fix the responsive image case without breaking itWhen using srcset/sizes, you still set width and height on the <img> to the dimensions of the default src. The browser scales the chosen candidate to that aspect ratio. Don't drop the attributes just because srcset is present — that's a common mistake that reintroduces the shift.
- Reserve space for lazy-loaded and JS-injected imagesIf JavaScript inserts images after load, give the placeholder element the final dimensions or aspect-ratio up front. Otherwise loading="lazy" trades one shift for another lower down the page.
- Audit the CMS output, not just one templateCheck what your theme or page builder actually renders — view source on a live page. If it's stripping dimensions site-wide, fix it at the template/plugin level so you don't play whack-a-mole on individual pages.
Stop it recurring
Make width/height (or an aspect-ratio rule) part of your image component so no image ships without reserved space.
Related errors