Cumulative Layout Shift measures unexpected visual movement during a page visit. A low CLS helps people keep their reading position and click the control they intended to use. A high CLS often points to media without dimensions, late injected content, unstable embeds, font swaps, or layout-changing animation.
CLS is one of the current Core Web Vitals. The reliable way to improve it is to find the largest shift cluster, identify what caused the movement, reserve the correct space, and validate the complete page lifecycle.
How CLS is measured
A layout shift entry measures the affected viewport area and the distance elements move. The browser groups shifts into session windows, and the page's CLS value is the largest session-window score during the visit. CLS is unitless; a value of 0.1 is not 100 milliseconds.
Shifts following recent user input are generally excluded because movement can be expected after an intentional action. That exclusion does not make every post-interaction layout good. A control that jumps away or content that reorders unexpectedly can still be a product problem.
The element shown as a shift source is often the element that moved, not necessarily the element that caused it. For example, a paragraph may move because an image above it loaded without reserved space. Inspect the surrounding layout and the event immediately before the shift.
What is a good CLS value
Google's current thresholds are:
| CLS | Rating |
|---|---|
| 0.1 or less | Good |
| Over 0.1 through 0.25 | Needs improvement |
| Over 0.25 | Poor |
Field assessment uses the 75th percentile of visits, segmented by mobile and desktop. The official CLS optimization guide documents the threshold and common causes.
A passing value is a baseline, not permission to ignore a visible shift. Prioritize movement near important controls, reading content, commerce actions, and forms even when the aggregate remains green.
Find the actual layout shift
Use Chrome DevTools Performance on the production route:
- Open a private window with extensions disabled.
- Record a page load in the Performance panel.
- Interact with menus, filters, consent, galleries, and lazy content.
- Inspect the Layout Shifts track and start with the largest cluster.
- Click individual shifts to see affected nodes and screenshots.
- Correlate the timestamp with network, script, font, and rendering events.
Test beyond initial load. A default Lighthouse run may miss a shift caused by scrolling, a delayed ad, a carousel, a route transition, or a consent action. Chrome's current Performance Insights reference includes a Layout shift culprits insight for trace-based attribution.
In your own real-user monitoring, the web-vitals library can attach bounded attribution data. Record route and component identifiers rather than sensitive text or form values. Aggregate by affected template and debug target so the most common field cause becomes visible.
Fix images and video
Give replaced media intrinsic dimensions so the browser can calculate an aspect ratio before bytes arrive:
<img
src="/products/analytics-dashboard-1200.webp"
srcset="/products/analytics-dashboard-600.webp 600w,
/products/analytics-dashboard-1200.webp 1200w"
sizes="(max-width: 720px) 100vw, 960px"
width="1200"
height="750"
alt="Analytics dashboard with traffic and conversion charts"
>
Responsive CSS can still size the image fluidly:
.article-image {
display: block;
width: 100%;
height: auto;
}
For art-directed <picture> sources with different crops, provide the correct dimensions on each source where supported and test each breakpoint. For video, poster images, and custom players, use aspect-ratio or another stable container before the player initializes.
Do not hard-code the wrong placeholder ratio. A reserved 16:9 box still shifts when the final asset is square.
Stabilize ads, embeds, and banners
Ads and third-party embeds often determine their final height after a request or auction. Reserve a slot based on the supported creative sizes and viewport. When several sizes are possible, choose a stable container strategy and accept unused space rather than collapsing and expanding the document unexpectedly.
.video-embed-shell {
aspect-ratio: 16 / 9;
width: 100%;
background: #f1f3f5;
}
.video-embed-shell iframe {
width: 100%;
height: 100%;
border: 0;
}
Cookie notices, promotional bars, install prompts, and newsletter forms can shift an entire viewport when inserted at the top. Safer choices include:
- render the reserved region in initial HTML;
- use an overlay when it is accessible and appropriate;
- place nonurgent content later in the document;
- keep a dismissed state from reappearing during navigation;
- avoid collapsing an empty ad slot while the user is reading nearby content.
Test the real production vendor. A local placeholder cannot reproduce auction sizes, consent timing, or widget initialization.
Handle dynamic application content
Skeletons prevent shifts only when they approximate the final layout. Match row count, media ratio, line height, and control dimensions closely. A tiny spinner replaced by a full product grid does not reserve meaningful space.
For feeds and “load more” interfaces, append below the user's current position rather than inserting above it. For validation errors, reserve space near fields or place messages without pushing the active control unexpectedly. For client hydration, ensure server and client markup agree; a hydration correction can move large regions.
Common application causes include:
- personalization replacing the server layout with a taller variant;
- A/B tests applying after first paint;
- prices or stock messages inserted above purchase controls;
- sticky headers changing height after scroll;
- accordions without a stable transition model;
- route transitions restoring the wrong scroll position.
Trace the state that triggers the shift and fix the component contract, not only its initial CSS.
Control font-related shifts
A web font can change line breaks, element widths, and control heights when it replaces a fallback. Reduce the number of font files and load only the weights used on the page. Use WOFF2 where appropriate, cache versioned font assets, and preload only a truly critical above-the-fold font.
Choose a fallback with compatible metrics. CSS font metric overrides such as size-adjust, ascent-override, descent-override, and line-gap-override can align a fallback when the font data supports a tested adjustment. They require measurement; copied values from another family can make the shift worse.
font-display: swap keeps text visible, but the later swap can still move layout. optional can avoid a late swap in some situations, but product and brand requirements should drive the choice. Test headings, buttons, navigation, and localized text at narrow widths.
Use layout-safe animation
Animating layout properties such as top, left, width, or height can move surrounding content. Prefer compositor-friendly transform and opacity when the visual design permits:
.notice {
transform: translateY(-8px);
opacity: 0;
transition: transform 180ms ease, opacity 180ms ease;
}
.notice[data-open="true"] {
transform: translateY(0);
opacity: 1;
}
This does not mean every transform is accessible or inexpensive. Respect reduced-motion preferences, avoid hiding essential content until an animation completes, and make sure transformed elements do not cover controls.
Explain lab and field differences
Field CLS can be worse than Lighthouse because real visits last longer and include scrolling, interactions, ads, personalization, route changes, and cached states. Lab CLS can also expose a cold-load problem that many field visitors avoid through cache.
Check:
- whether PageSpeed is showing URL or origin field data;
- the mobile or desktop segment;
- whether a lab user flow includes the relevant interaction;
- consent and authentication state;
- viewport and responsive breakpoint;
- the release date inside the rolling field window.
Do not dismiss field data as “wrong” because one local load is stable. Add field attribution or reproduce the complete user flow.
Validate the fix
After changing the component:
- Repeat the same trace at each relevant breakpoint.
- Test slow media, font, and third-party responses.
- Exercise consent, ads, filters, navigation, and dynamic content.
- Verify keyboard focus, screen-reader order, and reduced motion.
- Compare equivalent Lighthouse user flows.
- Deploy with monitoring and a rollback path.
- Watch real-user CLS through the full field-data window.
Review published performance histories on IndieTools Speed, and use What Are Core Web Vitals? when you need the broader assessment model. The fix is complete when the layout remains stable for real page states, not merely when one screenshot stops moving.


