At a glance
Cumulative Layout Shift at the 75th percentile. Measures unexpected visual movement of page content during the page lifecycle, expressed as a unitless score (not milliseconds, not pixels). Calculated as impact fraction × distance fraction summed across all unexpected shifts. Google’s “good” threshold is 0.1, sites at p75 CLS under 0.1 pass this CWV; over 0.25 is “poor”. Layout shift is the most viscerally annoying performance failure: customers tap a button, the layout shifts mid-tap, they tap the wrong thing. The metric directly correlates with rage-clicks, accidental cart-removals, and trust loss.
| What it counts | The 75th-percentile of cumulative_layout_shift measurements across all real-user page-loads in the 28-day CrUX window. Score is calculated as the sum of all “unexpected” layout shifts during the page lifecycle. A shift counts as unexpected unless it occurs within 500ms of a user input (clicks, taps, keypresses are excluded as expected user-driven shifts). |
| The score formula | Per shift: layout_shift_score = impact_fraction × distance_fraction. Impact fraction is the proportion of viewport affected; distance fraction is how far elements moved relative to viewport. Example: a banner shifting 33 percent of the viewport, 25 percent of the way down, scores 0.33 × 0.25 = 0.08. CLS is the sum across all shifts in the page session. |
| Sample type | Field data sourced from CrUX. Lab equivalent: psi_lab_cls. |
| Google thresholds | Good: ≤ 0.1. Needs improvement: 0.1-0.25. Poor: > 0.25. |
| Common ecommerce CLS patterns | (a) Hero banner without aspect-ratio reservation: image loads, layout shifts to accommodate. (b) Web font swapping mid-render: text reflows when custom font replaces fallback. (c) Late-loading widgets: Klaviyo popup, chat widget, currency switcher push content as they mount. (d) Ad placements without size reservation: ad slots size themselves at fill time, pushing content. (e) Cookie-consent banners: appear after first paint, pushing content. (f) Image upload via responsive <img> without explicit dimensions: browser doesn’t know size until image loads. |
| Optimisation playbook | (1) Declare aspect-ratio CSS on every image and video container: aspect-ratio: 16 / 9 reserves space before image loads. (2) Use width and height attributes on <img> tags so browser can compute aspect ratio. (3) Preload web fonts with <link rel="preload"> and use font-display: optional to avoid swap. (4) Reserve space for late-loading widgets: explicit min-height on chat widget container, Klaviyo popup container. (5) Reserve space for ad slots: min-height matching the ad creative’s size. (6) Use position: fixed for cookie banners to avoid pushing content. Each fix typically reduces CLS by 0.02-0.06; cumulatively can take a 0.18 score down to 0.05. |
| Sample size threshold | CrUX p75 requires sufficient real-user volume (~1,000+ page-loads per device per 28 days). |
| Currency | n/a, this is a unitless score. |
| Time window | 28D (CrUX-fixed). |
| Alert trigger | > 0.1 (Google’s good threshold). Sub-thresholds: amber 0.1-0.25, red > 0.25. |
| Sentiment key | psi_cls |
| Roles | owner, marketing, operations |
Calculation
Calculated automatically from your Website Performance (PageSpeed + CrUX) data. See the At a glance summary above for what the metric tracks and the worked example below for a typical reading.Worked example
A UK-based BigCommerce fashion store with 480,000 mobile page-views over 28 days, Stencil theme with hero banner + Klaviyo popup + chat widget + cookie consent banner. Snapshot Wednesday 15 May 26.| Layout shift event | Impact fraction | Distance fraction | Score | Cumulative CLS |
|---|---|---|---|---|
| Hero banner image loads (no aspect-ratio set) | 0.42 | 0.18 | 0.076 | 0.076 |
| Web font swap (Inter loading after fallback) | 0.85 | 0.04 | 0.034 | 0.110 |
| Cookie consent banner appears (top-fixed-then-pushes) | 0.18 | 0.21 | 0.038 | 0.148 |
| Klaviyo popup mounts (300ms post-load) | 0.12 | 0.16 | 0.019 | 0.167 |
| Chat widget icon appears (1.2s post-load) | 0.04 | 0.08 | 0.003 | 0.170 |
| Page-level CLS (mobile p75) | 0.170 |
- The 0.170 origin p75 CLS is in the “needs improvement” band (0.1-0.25). Not poor, but failing the good threshold and contributing to the all-three CWV pass-rate failure. The shifts compound: each individual shift might feel minor but the user experience is “the page jumps around for 1.5 seconds while loading”.
-
The hero banner is the biggest single contributor (0.076). With no aspect-ratio set on the banner container, the browser doesn’t reserve space until the image arrives; when it does, content below the banner pushes down by the banner’s height. One-line fix in CSS:
.hero-banner { aspect-ratio: 16 / 9; }. Estimated post-fix: 0.000 contribution from this shift; total CLS drops to 0.094. -
The web font swap (0.034) is the second-biggest contributor. When custom fonts (Inter, Poppins, etc.) load asynchronously, text initially renders in the fallback (Helvetica, Arial, system-ui), then swaps to the custom font when ready, causing every text element to potentially reflow. The fix has two parts: (a)
<link rel="preload" as="font" type="font/woff2" crossorigin>for critical fonts; (b)font-display: optionalso if the font isn’t ready in 100ms, fallback is used permanently for that page-load. Estimated post-fix: 0.005-0.010 contribution. -
Cookie consent banner (0.038) appears after first paint and pushes all content down. Fix: position the banner with
position: fixed; bottom: 0so it overlays content rather than displacing it. Most modern cookie-consent libraries support this layout; the merchant just needs to enable it. - Klaviyo popup (0.019) mounts as a JS-driven DOM insertion 300ms after page load. Fix: reserve a fixed-position container for the popup so the mount doesn’t displace surrounding content. Klaviyo’s modern popup config supports this.
-
Chat widget icon (0.003) is small but worth noting. Most chat widgets (Tidio, Intercom, Zendesk Chat, Drift) provide a
position: fixedmount option; ensure that’s the configured pattern. - Cumulative impact of all fixes: 0.170 → 0.025 (good band). Total work: ~1-2 days of focused CSS + integration config changes. The CLS fixes have the highest leverage-to-effort ratio of all CWV metrics: the underlying causes are well-understood and the fixes are mostly declarative.
- Open Chrome DevTools Performance tab and record the page load. The “Layout Shifts” lane shows each shift with timestamp, affected elements, and score contribution.
- Use the Web Vitals Chrome extension to see live CLS as you scroll/interact with the page.
- Identify the largest single shift.
crux_cls_distributionsurfaces the distribution; the worst single shift typically dominates the CLS score. - Check for late-loading widgets.
psi_third_party_costshows third-party scripts; many of them mount UI after first paint. - For the demo’s BC sandbox, the hero banner is the most likely dominant cause; fix it first.
| Time horizon | Action |
|---|---|
| First 1 hour after alert | Identify the largest single shift in DevTools. |
| First 4 hours | Apply aspect-ratio CSS fix to the worst element. |
| First 24 hours | Apply font-display + preload for web fonts. Reserve space for late-loading widgets. |
| First 7 days | Field CLS partial movement. Confirm direction. |
| Day 28 | Field CLS fully reflects fix. Move to next-priority shift if needed. |
Sibling cards merchants should reference together
| Card | Why merchants reach for it |
|---|---|
crux_cls_distribution | CLS good/needs-improvement/poor distribution. |
crux_cls_trend | CLS over time; drift detection. |
psi_lab_cls | Lab CLS, the synthetic equivalent. |
crux_lcp_p75 | Sister CWV; pair for the load + stability picture. |
crux_inp_p75 | Sister CWV. |
psi_cwv_pass_rate | All-three CWV gate. CLS failing alone fails the gate. |
psi_perf_score_summary | Composite score. CLS is 25 percent of the weight. |
psi_third_party_cost | Third-party scripts; common cause of late-loading content shifts. |
psi_image_optimisation | Image optimisation; correctly-dimensioned images are the biggest CLS fix. |
GA4 ga_engaged_sessions | Engagement metric; CLS-heavy pages reduce engagement. |
Reconciling against the vendor’s own dashboard
Where to look in PageSpeed Insights / GSC / CrUX’s own dashboards:- PageSpeed Insights, field section shows origin-level p75 CLS under “Cumulative Layout Shift”.
- Google Search Console → Core Web Vitals, surfaces URL groups failing CLS threshold.
- Web Vitals Chrome extension, measures CLS live as you scroll/interact.
- Chrome DevTools → Performance tab, visualises layout shift events with affected elements highlighted.
| Reason | Direction | What to do |
|---|---|---|
| Window timing. Vortex IQ refreshes daily; CrUX dataset has 1-2 day lag. | Vortex IQ lags for 1-2 days | Wait for next refresh. |
| Origin vs URL. Different aggregations for different views. | Different aggregation | Use per-URL view for direct comparison. |
| Form factor. Vortex IQ defaults to mobile. | n/a if both mobile | Confirm form factor. |
| CLS definition update May 2021. Google updated the CLS calculation in May 2021 to use “session windows” (1-second gaps reset the cumulative counter). Sites comparing year-over-year before the update see a methodology break. | Either direction | Anchor comparisons within the post-May-2021 era. |
| Comparison | Expected relationship | When divergence is legitimate |
|---|---|---|
crux_cls_p75 ↔ psi_lab_cls | Field and lab directionally agree | Lab measures one synthetic load; field measures real-user variation. Persistent gaps suggest CLS depends on user behaviour (scroll patterns, interaction timing). |
crux_cls_p75 ↔ Internal RUM CLS measurement | Should align within 0.02-0.05 | Cohort differences (CrUX is opted-in Chrome users; RUM samples your traffic). Modest divergence is normal. |
Known limitations / merchant FAQs
My CLS is 0.18 but the page doesn’t look like it’s jumping. Why? CLS accumulates across the entire page lifecycle, not just first paint. Many sites have small shifts spread across the load that individually feel minor but sum to a high score: hero image loading (0.05), font swap (0.03), late widget mounts (0.04), cookie banner (0.04), ad slot fill (0.02) = 0.18 cumulative even though no single shift is dramatic. Use Chrome DevTools’ Performance tab to see each individual shift; you’ll see all of them. Why is CLS so much harder to debug than LCP? CLS depends on timing, network conditions, and user interaction. LCP is largely deterministic (slow network = slow LCP); CLS varies by what the user does and when third-party scripts arrive. The same page can have CLS 0.05 with a fast cached load and CLS 0.30 with a cold-cache slow load. Reproducing CLS issues requires testing under varied conditions. Should I worry about CLS on pages that don’t get search traffic? Less. CLS affects ranking on traffic Google cares about (organic search). For internal admin pages, conversion-flow pages (cart, checkout), or paid-traffic-only landing pages, CLS matters for user experience but not for SEO. Focus CLS optimisation on high-organic-traffic templates first (homepage, category, PDP); de-prioritise on transactional pages. Will adding aspect-ratio CSS to all my images break the layout? Generally no, with one caveat.aspect-ratio reserves space matching the declared ratio; if the actual image is a different ratio, the image may be letter-boxed or stretched depending on object-fit. Best practice: set aspect-ratio per image based on the actual image dimensions (using inline style attributes if dimensions vary), or standardise image dimensions at upload time. For BC themes with merchant-uploaded product images of varying dimensions, the width and height HTML attributes (not CSS aspect-ratio) work better because they accept per-image values.
My CLS is fine on most pages but bad on the homepage. Is that OK?
Depends on traffic share. If the homepage is 10 percent of traffic, the homepage’s bad CLS contributes proportionally to the origin-level pass rate. If the homepage is 40 percent of traffic, fixing it lifts the origin pass rate noticeably. The fix decision is the same, fix the worst-offending page, but the urgency scales with traffic share.
Cookie consent banners are a legal requirement. Can I avoid the CLS impact?
Yes, with proper layout. Position the banner with position: fixed; bottom: 0 (or top: 0) so it overlays content rather than displacing it. Most modern cookie consent libraries (OneTrust, Cookiebot, BC’s built-in consent) support this layout pattern. Avoid the legacy “push content down” pattern which was common 5 years ago but is now considered both UX-poor and CLS-bad.
Will Lighthouse score CLS the same as the field measurement?
Approximately, but with caveats. Lab Lighthouse measures CLS during a single synthetic page-load with controlled conditions; field CrUX measures the distribution across all real-user sessions including those with interactions, scrolling, and multiple navigations. Lab CLS is typically lower than field CLS because lab can’t capture user-interaction-triggered shifts. Use lab as a development tool; field as the truth source.
Can Vortex IQ identify the specific element causing the worst shift?
Yes, indirectly. Lighthouse’s “Avoid large layout shifts” audit (surfaced via psi_top_opportunities_ms) lists shifting elements with their score contributions. The Vortex IQ audit module flags the top 3 shifting elements per template.
My BC site’s CLS got worse after I added a chat widget. What can I do?
Most chat widgets default to a position: relative mount that can shift content. Switch the widget to position: fixed mode (Tidio, Intercom, Zendesk Chat all support this) and reserve a fixed-pixel container. Alternatively, configure the widget to load only after first paint (Klaviyo + most chat widgets support display_after_seconds: 3 or similar), by then the user has already seen and engaged with the page, and the widget mount doesn’t disrupt their experience.
How long does it take to fix CLS from 0.18 to 0.05?
Usually 1-3 days of focused work for a typical Stencil-themed BC site, longer for custom-built sites. The fixes are mostly declarative CSS changes plus widget-config tweaks; the constraint is identifying every contributing shift, not implementing each fix.