Cumulative Layout Shift (CLS) scores above 0.1 are classified as "needs improvement" by Google's Core Web Vitals thresholds, and scores above 0.25 are "poor." Fixing CLS before it ships to users is cheaper than recovering lost rankings after the fact — start with measurement, then fix root causes in priority order.
What Is Cumulative Layout Shift?#
CLS is a Core Web Vitals metric that quantifies how much visible page content moves unexpectedly during the entire lifespan of a page visit. Each individual layout shift contributes a score equal to the impact fraction (how much of the viewport moved) multiplied by the distance fraction (how far it moved). Google aggregates these into a session-window score and reports the worst window.
A score of 0 means nothing moved. A score of 0.1 or below is "good." Anything above that is a measurable UX and ranking liability.
Why Does CLS Still Matter in 2026?#
Google uses field data from Chrome User Experience Report (CrUX) — not just lab data — to evaluate Core Web Vitals for ranking. CLS is one of three signals in the Page Experience update alongside Largest Contentful Paint (LCP) and Interaction to Next Paint (INP).
Beyond rankings, high CLS causes real harm: users accidentally tap the wrong button, forms reset, and reading flow breaks mid-sentence. These outcomes increase bounce rates and reduce conversion.
How Do You Measure CLS Accurately?#
Use both lab and field tools, because they capture different failure modes.
Lab tools (for debugging):
- Chrome DevTools Performance panel — record a page load and inspect Layout Shift clusters in the Experience track
- Lighthouse (built into DevTools or CLI) — flags CLS and links to contributing elements
- WebPageTest — provides filmstrip view so you can visually verify when shifts happen
Field tools (for real-user data):
- Google Search Console → Core Web Vitals report — shows CLS status grouped by URL type
- PageSpeed Insights — blends CrUX field data with Lighthouse lab data on the same screen
- Web Vitals JavaScript library (
web-vitals npm package) — lets you log CLS to your own analytics
Always prioritize fixing URLs flagged as "poor" in Search Console first, because those affect ranking directly.
What Causes High CLS?#
The vast majority of CLS problems fall into a small set of root causes.
Images and videos without explicit dimensions
When the browser does not know an image's dimensions before it loads, it allocates zero space. The image then pushes content down when it arrives. Fix: always set width and height attributes on <img> and <video> elements, and use CSS aspect-ratio as a fallback.
Ads, embeds, and iframes with no reserved space
Third-party ad slots and social embeds inject content asynchronously. The browser has no advance warning of their size. Fix: reserve the maximum expected slot height with a CSS placeholder before the ad loads.
Web fonts causing FOUT or FOIT
Flash of Unstyled Text (FOUT) or Flash of Invisible Text (FOIT) cause text reflow when the custom font swaps in, shifting surrounding elements. Fix: use font-display: optional for non-critical fonts, or font-display: swap combined with size-adjust and ascent-override descriptors to match fallback metrics to the custom font.
Dynamically injected content above existing content
Banners, cookie consent notices, and "sticky" headers inserted above the fold after initial render push the page down. Fix: pre-render these elements server-side, or use CSS position: fixed / sticky so they overlay rather than displace content.
Animations using layout-triggering CSS properties
Animating top, left, width, height, or margin forces layout recalculation and contributes to CLS. Fix: animate only transform and opacity, which are composited on the GPU and do not trigger layout.
This is the highest-impact fix for most sites.
- Audit every
<img> tag — confirm both width and height attributes are present with the intrinsic pixel dimensions.
- Add CSS
img { height: auto; } globally so responsive scaling still works even when explicit dimensions are set.
- For responsive images using
srcset, set the largest dimensions as the width/height attributes — the browser uses the aspect ratio, not the literal size.
- For
<picture> elements with art-direction crops at different breakpoints, use the aspect-ratio CSS property per breakpoint in a <style> block.
- For lazy-loaded images below the fold, still include dimensions — lazy loading delays the fetch but not the space allocation.
Font-swap CLS is subtle but measurable, especially on text-heavy pages.
- Self-host fonts whenever possible to eliminate DNS lookup latency that delays font availability.
- Use
<link rel="preload" as="font"> for the primary body font so it arrives before first paint.
- Add
font-display: optional for decorative fonts that are not critical to layout — the browser uses the fallback if the font isn't cached, avoiding any swap.
- Use the
size-adjust, ascent-override, and descent-override CSS descriptors inside @font-face to match your fallback font's metrics to the custom font, eliminating reflow on swap.
- Test with the Network tab throttled to Slow 3G to reproduce worst-case swap scenarios.
How Do You Fix Ad and Third-Party CLS?#
Third-party content is the hardest CLS source to control because you don't own the code.
- Reserve explicit slot dimensions. Wrap every ad or embed in a container with a fixed
min-height matching the largest expected creative size.
- Use a CSS skeleton placeholder. A gray background block the same size as the expected ad prevents a jarring blank-then-content shift.
- Load third-party scripts with
async or defer. Scripts that block the main thread delay the point at which reserved space is filled, extending the shift window.
- Audit with WebPageTest's "Block" feature. Block individual third-party domains to isolate which script causes which shift.
- Consider moving consent banners and cookie notices to overlay modals rather than top-of-page banners that displace content.
How Do You Use the bfcache to Prevent CLS on Navigation?#
The back-forward cache (bfcache) restores a fully rendered page snapshot when users navigate back or forward, eliminating layout shifts caused by re-loading dynamic content. Most modern browsers support bfcache, but pages with unload event listeners, Cache-Control: no-store headers, or IndexedDB transactions in flight are ineligible.
To maximize bfcache eligibility:
- Remove all
unload event listeners; replace with pagehide
- Avoid
Cache-Control: no-store on pages that don't contain sensitive data
- Close open
IndexedDB connections before the user navigates
This is a 2025–2026 priority because Google now measures CLS across navigations, not just initial loads.
How Do You Validate Fixes Before Deploying?#
Never ship CLS fixes blind — verify in a staging environment first.
- Run Lighthouse against the staging URL and confirm the CLS score drops to 0.1 or below.
- Record a Performance profile in Chrome DevTools and confirm no Layout Shift entries appear in the Experience track during the critical user journey.
- Use the
PerformanceObserver API with type: 'layout-shift' to log individual shift entries during QA testing:
js
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log('Layout shift value:', entry.value, entry);
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
- After deploying, monitor Search Console's Core Web Vitals report. Field data typically updates within 28 days as new CrUX data is collected.
What Is a Good CLS Score Target for 2026?#
Aim for 0.1 or below. Many high-quality sites achieve 0.05 or lower. The practical ceiling for "no visible shift" that most users perceive is approximately 0.05 — above that, subtle movements become noticeable, especially on mobile devices where viewport fractions are larger in absolute pixel terms.
Prioritize mobile CLS separately from desktop. Google's ranking signals draw from mobile CrUX data for mobile-indexed pages, and mobile viewports make every layout shift more visually impactful.
CLS Fix Priority Order#
When time is limited, fix in this order based on frequency and impact:
- Images without dimensions — broadest impact, easiest fix
- Font swap reflow — high impact on text-heavy pages
- Above-fold dynamic content (banners, notices) — immediate visual disruption
- Ad and embed slot reservation — difficult but essential for ad-supported sites
- Layout-triggering animations — usually lower CLS contribution but worth auditing
- bfcache eligibility — modern priority, easy wins with
unload listener removal