A decade of Canvas at your command — powered by our custom AI engineStart Building →
Glossary

What Is Cumulative Layout Shift (CLS)?

Cumulative Layout Shift (CLS) is a Core Web Vital metric defined by Google that quantifies the visual instability of a webpage by measuring the sum of all unexpected layout shift scores during the entire lifespan of a page. Each layout shift score is calculated as the product of the 'impact fraction' (the viewport area affected) and the 'distance fraction' (the furthest distance any element moves relative to the viewport). A CLS score below 0.1 is considered 'Good', 0.1–0.25 is 'Needs Improvement', and above 0.25 is 'Poor'.

What Is Cumulative Layout Shift (CLS)?

Cumulative Layout Shift (CLS) is a Core Web Vital metric defined by Google that quantifies the visual instability of a webpage by measuring the sum of all unexpected layout shift scores during the entire lifespan of a page. Each layout shift score is calculated as the product of the 'impact fraction' (the viewport area affected) and the 'distance fraction' (the furthest distance any element moves relative to the viewport). A CLS score below 0.1 is considered 'Good', 0.1–0.25 is 'Needs Improvement', and above 0.25 is 'Poor'.

How Cumulative Layout Shift (CLS) Works

CLS is measured by the browser's Layout Instability API (part of the W3C Web Performance Working Group specification), which fires a `layout-shift` PerformanceEntry event whenever an element moves between two rendered frames without a user-initiated interaction. The shift score for each event is computed by multiplying two fractions: the impact fraction (the union of the element's before-and-after bounding boxes as a proportion of the total viewport area) and the distance fraction (the greatest distance any shifting element traveled divided by the largest viewport dimension). Only 'unexpected' shifts count — movements triggered within 500ms of a user input (click, keypress, tap) are excluded via the `hadRecentInput` flag on the PerformanceEntry. Google's tooling (Lighthouse, PageSpeed Insights, Chrome UX Report) aggregates individual shift entries using a 'session window' model introduced in 2021: shifts are grouped into windows where each shift occurs within 1 second of the previous one and the total window duration doesn't exceed 5 seconds. The worst such session window defines the page's CLS score, preventing a single late-loading ad or font swap from catastrophically inflating scores on long-lived single-page applications. Common causes of high CLS include images and video embeds rendered without explicit `width` and `height` attributes (so the browser doesn't reserve space during HTML parsing), dynamically injected content such as ad banners or cookie consent banners inserted above existing content, web fonts that trigger FOUT (Flash of Unstyled Text) or FOIT (Flash of Invisible Text) causing text reflow when the font loads, and animations that modify layout-triggering CSS properties like `top`, `left`, `margin`, or `height` instead of compositor-friendly properties like `transform` and `opacity`. The browser calculates layout shifts at the pixel level using the Intersection Observer and ResizeObserver internals, reporting them asynchronously through the PerformanceObserver API. Developers can tap into this directly with `new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (!entry.hadRecentInput) clsScore += entry.value; } }).observe({ type: 'layout-shift', buffered: true })`, enabling real-user monitoring (RUM) of CLS in production environments beyond what lab tools like Lighthouse can capture.

Best Practices for Cumulative Layout Shift (CLS)

Always declare explicit `width` and `height` attributes on `<img>`, `<video>`, and `<iframe>` elements so the browser can compute the correct aspect-ratio box before the resource loads — modern browsers use these attributes to set the intrinsic `aspect-ratio` via the UA stylesheet, entirely reserving the space without a placeholder. For dynamically loaded content like ads, cookie banners, or chat widgets, pre-allocate space using `min-height` on a container or render the component in a reserved slot below the fold rather than injecting it above existing content. Replace FOUT-inducing font strategies with `font-display: optional` for non-critical typefaces or `font-display: swap` combined with `<link rel='preload'>` for primary fonts, and use `size-adjust`, `ascent-override`, and `descent-override` CSS descriptors to create metric-compatible fallback fonts that eliminate reflow when the web font arrives. For animations and transitions, exclusively use `transform: translate/scale/rotate` and `opacity` changes rather than animating `width`, `height`, `top`, `left`, or `margin`, as transform and opacity changes run entirely on the GPU compositor thread and do not trigger layout recalculation. Finally, use `content-visibility: auto` cautiously — while it improves rendering performance, pair it with `contain-intrinsic-size` to prevent layout shifts when off-screen sections become visible.

Cumulative Layout Shift (CLS) & Canvas Builder

Canvas Builder's Bootstrap 5 output provides a structurally sound foundation for low CLS by default: Bootstrap's grid system uses `flexbox` and `css grid` with explicit column sizing, so layout containers don't collapse or reflow when dynamic content loads — a key structural defense against layout instability. The clean, semantic HTML Canvas Builder exports includes properly sized media containers and avoids anti-patterns like inline `style` overrides that disrupt aspect-ratio preservation, meaning developers inherit a CLS-friendly codebase without manual auditing. For teams deploying Canvas Builder-generated pages at scale, this consistency translates directly into predictable Core Web Vitals scores across all generated templates, reducing the debugging burden and supporting stronger, more uniform SEO performance across the entire site.

Try Canvas Builder →

Frequently Asked Questions

What is a good CLS score and how is it measured in real-user data vs. lab data?
A CLS score of 0.1 or below is classified as 'Good' by Google's Core Web Vitals thresholds, while 0.1–0.25 is 'Needs Improvement' and anything above 0.25 is 'Poor'. Lab tools like Lighthouse simulate a single page load in a controlled environment and may miss shifts that only occur in real-world conditions (slow 3G, cold cache, A/B test variants), so it's essential to also monitor field data via the Chrome UX Report (CrUX) or a RUM solution — Google Search Console's Core Web Vitals report surfaces the 75th-percentile CLS from real Chrome users, which is the authoritative score for SEO purposes.
Why does CLS still appear high on single-page applications (SPAs) even after fixing images and fonts?
SPAs frequently cause CLS during client-side route transitions because new route content is injected into the DOM after the initial paint — skeleton screens or loading spinners that later collapse and re-expand with real content are a common culprit, as the transition between placeholder and content dimensions registers as a layout shift. Additionally, SPA frameworks like React and Vue may trigger multiple synchronous DOM mutations during hydration or state updates that each individually contribute small shift values that accumulate into a high CLS score. The fix involves using CSS `min-height` reservations on dynamic content containers, deferring non-critical content loads with Suspense boundaries, and ensuring client-side navigation preserves the scroll position and layout dimensions of persistent UI elements like headers and sidebars.
How does Canvas Builder's HTML output help achieve a low CLS score?
Canvas Builder generates clean, standards-compliant HTML5 with Bootstrap 5, which means layout components like grid columns, cards, and image containers are built on a flexbox/grid foundation with well-defined proportional sizing — this structural predictability prevents the unsized-element problem that is the single largest source of high CLS scores. Bootstrap 5's `.ratio` utility classes (e.g., `ratio ratio-16x9`) and Canvas Builder's image export pipeline automatically embed explicit `width` and `height` attributes on `<img>` tags, ensuring browsers reserve the correct intrinsic size before images load. The semantic, single-pass HTML structure Canvas Builder produces also avoids the pattern of injecting content above-the-fold after initial render, meaning pages built with Canvas Builder start with a strong CLS baseline out of the box.