Skip to content

Performance · Next.js (App Router)

How to fix cumulative layout shift from images in Next.js (App Router)

The browser cannot reserve space for an image whose size it does not know, so the page reflows as each one arrives. That is layout shift — the CLS metric — and it is why text jumps under someone's finger as they go to tap. Declaring the intrinsic width and height fixes it without changing how the image is styled.

The fix for Next.js (App Router)

13x detects your framework from the response and hands you this version rather than the generic one — below 50% confidence it hedges and gives you the generic one instead.

Use next/image, which requires dimensions and handles format conversion and lazy loading too:

tsx code
import Image from "next/image";

<Image src="/hero.png" width={1200} height={630} alt="…" priority />

// For a fill layout, the parent needs position and a known aspect:
<div className="relative aspect-[1200/630]">
  <Image src="/hero.png" fill alt="…" style={{ objectFit: "cover" }} />
</div>

Set priority on the largest above-the-fold image — that one should not be lazy-loaded. For a statically imported image, the dimensions are inferred and you can omit them.

On a different stack? The general version of this fix explains what 13x checks and why it matters, without assuming a framework.

Check your Next.js (App Router) site

113 deterministic checks against your live URL, in about 30 seconds. Framework detected from the response, so every fix comes back in the form your stack actually uses.

No signup. Results in 30 seconds.