CLS — Cumulative Layout Shift

How much visible content unexpectedly moved after rendering. A score of 0 means nothing shifted.

CLS quantifies how much visible content unexpectedly moves after it has been rendered. A high CLS means users are reading text that suddenly jumps, or clicking a button that shifts away at the last moment.

Unlike time-based metrics, CLS is a unitless score: the product of the shifted element's size (relative to the viewport) and the distance it moved. Multiple shifts are summed together.

What counts and what doesn't

Only unexpected shifts count. Shifts that happen within 500 ms of a user interaction — click, tap, keypress — are excluded by the browser. The reasoning is that if a user clicked a button that caused content to change, that shift is expected.

Shifts that do count include: late-loading ads or embeds pushing content down, images without explicit dimensions, web fonts causing text reflow (FOIT/FOUT), and dynamically injected banners or cookie notices.

How Witnes captures it

Witnes uses a PerformanceObserver listening for layout-shift entries with buffered: true. Each entry is checked for hadRecentInput; entries with recent input are silently discarded. The remaining shift values are accumulated into a running total throughout the session.

For SPA navigations, Witnes tracks a per-navigation baseline so only shifts since the route change are attributed to that navigation.

What good looks like

Witnes uses different thresholds than Google Web Vitals. The table shows both for comparison:

Score Witnes Google Web Vitals
< 0.1 Good Good
0.1 – 0.15 Good Needs Improvement
0.15 – 0.25 Needs Improvement Needs Improvement
> 0.25 Poor Poor

Witnes's Good threshold (0.15) is wider than Google's (0.1) because Overall Health requires both LCP and CLS to pass simultaneously — a combined requirement justifies a slightly wider individual threshold.

CLS in other scores

In the session-level Sentiment Score, CLS is evaluated separately with a higher threshold: a CLS above 0.5 triggers the Unstable Layout symptom. This is intentional — the Sentiment Score captures multiple dimensions, so a moderate layout shift on an otherwise fast page should not immediately grade a session as Bad.

Further reading

Cumulative Layout Shift (CLS) — web.dev