Why the layout jumps
When the browser builds a page, it doesn't know an image's size until the image has loaded. If there's no size given, it reserves no space for it — the text below slides up as if the image weren't there. As soon as the image arrives, it pushes in and shoves everything down. That's the exact moment the page “jumps.” Google measures this as Cumulative Layout Shift (CLS) — one of the Core Web Vitals — and treats strong jumps as a poor user experience.
The fix: tell the browser the dimensions
Give every image its real pixel dimensions as width and height:
<img src="photo.jpg" alt="..." width="1200" height="800">The browser computes the aspect ratio from them (here 3:2) and immediately reserves a placeholder at the right height — before the image loads. When the image arrives, it fills exactly the space held for it, and nothing jumps. Two numbers, problem solved.
“But then my image isn't responsive anymore!”
The most common objection — and a misunderstanding. The HTML attributes only set the aspect ratio, not a fixed display size. With a little CSS the image stays fully flexible:
img {
width: 100%;
height: auto;
}So the image still scales with its container — the browser uses the attributes solely to hold the space in the right ratio ahead of time. Responsive and jump-free aren't mutually exclusive.
The modern variant: aspect-ratio
When the pixel dimensions aren't available as attributes (dynamic images, video embeds, containers with a background image), the CSS property aspect-ratio helps:
.image-container {
aspect-ratio: 16 / 9;
width: 100%;
}The container always keeps its 16:9 ratio and reserves the space regardless of when the image loads. Ideal for gallery tiles and embedded media.
Interplay with lazy loading
With lazy-loaded images the size hint is doubly important: they deliberately appear later — without reserved space the jump on load would be guaranteed. loading="lazy" and width/height therefore always belong together.
Other common CLS sources (briefly)
- Web fonts that load late and reflow text — control with
font-display. - Ads and embeds with no reserved space — give the container a fixed height.
- Dynamically inserted banners at the top of the page — better below, or with reserved space.
But images are the most common and most easily fixed cause. How CLS fits into the overall Core Web Vitals is covered in Improving Core Web Vitals.
In short
- Always set
widthandheight— reserves the space. width:100%; height:autokeeps it responsive.aspect-ratiofor dynamic/embedded media.- Pair it with lazy loading — never lazy-load without dimensions.