Cumulative Layout Shift (CLS) is the Core Web Vital for visual stability. It scores how much visible elements jump around without the user causing it, such as text moving down when an image or banner loads above it. Google rates CLS as good at 0.1 or less and poor above 0.25, at the 75th percentile of visits.
How the score is calculated
Each unexpected shift gets a score from two factors: how much of the viewport the moving elements affect (impact fraction) and how far they move (distance fraction). Shifts are grouped into session windows, where shifts less than one second apart join the same window, capped at five seconds. CLS reports the largest window during the visit.
Shifts that happen within 500 milliseconds of a user input, like opening an accordion the user clicked, are excluded, because the user expected them.
Common causes
Most layout shift comes from the browser not knowing how much space something will need.
- Images, videos and iframes without width and height or aspect-ratio
- Cookie banners, promo bars and chat bubbles inserted above existing content
- Web fonts swapping in with different metrics from the fallback font
- Ads or embeds that resize after loading
- Content injected after a client-side data fetch
Fixes
Reserve space. Set width and height on images and video so the browser can compute the aspect ratio before the file arrives. Give embeds and dynamic slots a minimum height. Show banners as overlays rather than pushing content down, or render them on the server so they are present from the first paint. For fonts, use size-adjust and related descriptors to match fallback metrics, or preload key fonts.
/* Reserve space for a product video embed */
.demo-video {
aspect-ratio: 16 / 9;
width: 100%;
}
/* Match fallback font metrics to reduce shift on swap */
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
}Example
The announcement bar that pushed the page down
Picture a fictional collaboration SaaS, Threadly, that shows a "New: AI summaries" bar at the top of every page. It is fetched from a feature-flag service after load and inserted above the header, shoving the whole page down. CLS fails on every template.
Rendering the bar on the server when it is active, or reserving its height in the layout, removes the shift.
Common mistakes
Only checking the first few seconds
CLS is measured across the visit. Shifts from lazy-loaded content further down, or late-loading widgets, still count.
Assuming lab CLS matches field CLS
Lab tests often stop early and do not scroll. Field data captures shifts that happen as real users scroll and interact.
Questions
Animations using CSS transform do not cause layout shifts. Animating properties like top, height or margin can.
No. Shifts within 500 milliseconds of a user input are excluded.