AIWebPageSEO CLS Debugger Fixes Fix CLS in React / Next.js

How to Fix CLS in React / Next.js

React and Next.js CLS issues are different from server-rendered platforms: hydration mismatches cause flash-of-different-content, client-only components shift in after hydration, next/font and next/image work IF configured correctly. This guide covers React/Next.js-specific CLS. Pair with CLS guide.

Step-by-step: How to fix CLS in React / Next.js

  1. Baseline measurement. PageSpeed Insights or Chrome DevTools Performance Insights → CLS measurement. Mobile field data via CrUX (Search Console Core Web Vitals report).
  2. Use next/image with explicit dimensions. Next.js next/image requires width/height or fill prop. Auto-handles srcset, WebP/AVIF, lazy loading. Never use raw <img> for content images — CLS protection only via next/image.
  3. Use next/font for fonts. Next.js next/font (Google Fonts or local) eliminates font-swap CLS by automatically including font-display: optional and sizing fallback fonts. Migrate from manual @import or <link> font loading.
  4. Reserve space for client-only components. Components rendered only after hydration (e.g., dynamic({ ssr: false })) appear empty server-side, then populated after hydration — pushing content down. Fix: render a placeholder with the same dimensions during SSR, replace on hydration.
  5. Fix hydration mismatch warnings. Console errors like 'Text content does not match' indicate server HTML differs from client render. Causes flash + CLS. Common: Date.now(), Math.random(), localStorage usage during render. Use useEffect for client-only data or suppressHydrationWarning sparingly.
  6. Audit third-party scripts. Tag managers, chat widgets, analytics injected as <script> tags shift content. Use next/script with strategy='lazyOnload' for non-critical scripts, position them in reserved containers.
  7. Monitor and iterate. Real User Monitoring (Vercel Analytics, Sentry Performance, SpeedCurve) tracks CLS from real users. Lab data (PageSpeed) often shows better CLS than field data — field is what Google ranks.
Tip. Pin your framework, dependency, and config versions in a single internal doc (Next.js version, React version, rendering strategy choices, custom config). When something breaks after a framework or library update, you have a baseline to compare against.

🔎 Audit React CLS

Identify hydration, image and font causes of layout shift.

Run CLS Debugger →

Frequently Asked Questions

Why does my Next.js site have high CLS despite using next/image?

Common: next/image used without width/height (then must use fill prop with relative parent — easy to misconfigure). Or images are responsive but not given aspect-ratio CSS — image area not reserved until image loads. Audit each image in DevTools: should reserve full space before src loads.

How does next/font fix CLS?

Two ways: 1) Inlines font CSS so no extra network request blocks render. 2) Calculates fallback font's size-adjust value automatically so swap from fallback to web font doesn't shift text. Effectively eliminates font-swap CLS. Replace manual font loading with next/font.

What's hydration mismatch and how does it cause CLS?

Server renders one HTML, client renders different HTML on first React render. Browser shows server version briefly, then React rerenders to client version — visible flash and potential layout shift. Causes: time-dependent logic during render, browser-only APIs accessed during SSR, undefined-checks that differ server vs client.

Should I use Suspense for code splitting on Next.js?

Yes for non-critical components. Suspense boundaries with skeleton fallbacks reserve space during load — no shift when content arrives. Avoid Suspense boundaries on critical above-fold content (delays user-visible content).

Why do third-party widgets cause CLS in Next.js?

They inject content post-hydration, pushing existing content. Fix: render an empty <div> with known dimensions as their target. Most widget vendors (Intercom, Drift, Crisp) document expected dimensions.

Got a problem?