Why CLS differs between lab and field measurements
A frequent source of confusion is a mismatch between the CLS reported by the Chrome UX Report (CrUX) and the score produced by lab tools like Lighthouse. The gap usually comes down to measurement windows. Lab tools typically assess the initial page load only, while CrUX tracks CLS over the full lifetime of the page.
Layout shifts are common during load, but they can also occur well after rendering finishes. Many post-load shifts are the result of user interactions and are automatically excluded from CLS because they fall within the 500 ms grace period following the interaction. Others are unexpected: lazy-loaded content that displaces page elements as the user scrolls, or transitions in single-page applications that exceed the grace period. When lab scores are close to field scores, the problem is almost certainly load-time CLS. A significant divergence points to post-load shifts that lab runs cannot capture.
Finding load-time shifts
When Lighthouse and CrUX agree, Lighthouse's CLS audits can help you trace the problem. Filter the audits to reveal diagnostics for images that lack explicit dimensions and to list the elements that shifted during page load along with each one's CLS contribution.
The DevTools Performance panel offers a richer view. A dedicated Layout shifts track shows shift clusters as purple bars, with individual diamonds sized in proportion to the magnitude of each shift. Selecting a shift displays an animated summary plus the shifted elements in purple. The Summary view for a Layout Shift record includes the start time, shift score, and affected elements — useful detail for load CLS since it can be reproduced reliably by profiling a reload. The Insights panel adds a Layout shift culprits entry with the total CLS and likely reasons for the shifts.
Isolating post-load shifts
Post-load CLS is harder to reproduce. The live metrics view in the Performance panel lets you interact with the page while monitoring the CLS score, which helps surface interactions that trigger large shifts. If you prefer the console, you can record shifts with a Performance Observer passed in directly.
Once monitoring is set up, scroll through the page and hover over elements to mimic real usage. Shifts triggered by scrolling or hover still count toward CLS even within the 500 ms window because they are not considered user-initiated. For controlled regression checks, the timespan mode of Lighthouse user flows can verify that typical flows do not introduce new shifts.
Collecting field data on shift culprits
Field-level attribution narrows down the circumstances surrounding your CLS issues and helps you prioritize fixes. Lab tools typically report only which elements shifted, which is usually sufficient to identify the root cause, but field data can reveal patterns tied to particular user journeys. The web-vitals library provides attribution functions for this purpose. Several commercial RUM providers now expose similar shift-level data as well.
Eliminating the Most Frequent CLS Culprits
Once CLS sources are identified, the fixes usually fall into a few familiar categories. The most common offenders—and the strategies to neutralize them—are covered below.
Undimensioned Images and Video
Always specify width and height attributes on your <img> and video elements, or reserve the space they will occupy with CSS aspect-ratio. This lets the browser allocate the correct space in the layout while the asset is still downloading.
Modern browsers derive a default aspect ratio from the width and height attributes you provide. The browser uses this ratio at the very start of layout calculation to determine the element's height, even before the image arrives. So pair those attributes with a CSS rule that allows the element to scale responsively without breaking the ratio:
img {
width: 100%;
height: auto;
aspect-ratio: attr(width) / attr(height);
}
This prevents the text below an image from jumping down as the image loads. The auto keyword in the CSS property is important: after the image downloads, the actual dimensions override the computed default. If the HTML attributes are incorrect, this still produces some shift, but it's far less than the 0x0 shift of an image with no dimensions at all. Note how this computed aspect-ratio appears in DevTools: Chrome and Safari display it as an "HTML Attributes" style source, while Firefox uses it for layout without showing it in the Inspector.
This required space reservation was standard practice before responsive design. Developers originally wrote fixed pixel sizes into markup and reduced layout jank. When srcset and fluid layouts became the norm, the attributes were dropped, and jank returned. The modern recommendation restores those attributes while keeping CSS in charge of the final presentation.
For responsive images: when using srcset, each candidate for the browser to choose from should share the same aspect ratio:
<img
width="1000"
height="1000"
src="puppy-1000.jpg"
srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w"
alt="Puppy"
/>
If you're doing art direction with a <picture> element, the different images may have intentionally different aspect ratios. Current versions of Chrome, Firefox, and Safari support the width and height attributes directly on <source> elements inside <picture>. Best to add them there.
Late-Injected Content
Ads, embeds, iframes, and widgets are frequent sources of layout shift because their hosts often don't know their final size in advance. Dynamic ad sizing, for instance, favors revenue but pushes content down when a larger ad wins the slot.
Injection strategies break down into a few methods, typically limited by how much control you have over the third party.
Reserve space upfront. For content within the normal flow, reserve space with min-height or aspect-ratio. Use media queries to account for size differences across form factors. If the exact size is variable (more common with ads), choose the smallest anticipated size or the most likely size based on historical data, and accept some shift for larger variants. Resist collapsing the reserved space when no content is served—removing space causes as much damage as adding it.
Push it down. If space reservation is impossible, place the element lower on the page, where shifts have a smaller CLS impact.
Require a user gesture. Avoid surprising users with pop-in banners and forms that shift content when the page loads. Reserve the space ahead of time, or deliberately overlay the new element so it doesn't displace the document flow. When dynamically adding content is essential to the experience, such as paginating a product list or refreshing a feed, rely on user-initiated actions like "Load more" or "Refresh." Shifts occurring within 500 milliseconds of user input are not counted towards CLS. Alternatively, update content in a fixed-size container, or load it offscreen and surface a notice to the user.
Animations That Cause Reflow
Animating certain CSS properties comes with a hidden cost. Changes to box-shadow or box-sizing trigger re-layout, paint, and composite. Animating top and left causes layout shifts, even if the element is on its own layer. Use transform instead to translate, scale, rotate, or skew. Composited translate animations affect no other elements. Even non-composited animations avoid causing re-layout. Choosing the right properties keeps motion from disturbing the page's stability.
Web Fonts and Shifting Text
Both swap and invisible-text (FOIT) font loading strategies can cause layout shifts. Even invisible text still occupies layout space with the fallback font; when the web font arrives, the page reflows. Mitigate this with a layered approach:
font-display: optionallimits use of the web font to initial layout, preventing a swap re-layout.- Be explicit about the fallback to match your intent. For example,
font-family: "Google Sans", sans-serif;instructs the browser to use a sans-serif fallback while the custom font loads. Omitting the fallback, in Chrome, results in a serif (Times) fallback, which is a terrible visual match for most webfonts. - Minimize the metric gap between fallback and webfont with the newer descriptor APIs:
size-adjust,ascent-override,descent-override, andline-gap-override. - Cut the time to get necessary fonts with the Font Loading API, and preload critical files with
<link rel="preload">. If the font is loaded before first paint, there's no shift at all.
The Back/Forward Cache as a CLS Mitigation
One of the most effective ways to keep CLS scores low across a user's journey is to ensure your pages are eligible for the browser's back/forward cache (bfcache).
The bfcache preserves a snapshot of a page in memory after the user navigates away. If they then return via the back or forward button, the page is restored immediately and exactly as it was left. This eliminates any layout shifts that would typically occur during a fresh page load due to the various factors discussed earlier.
While this does not prevent layout shifts on the initial load, it prevents users from repeatedly experiencing the same shifts when navigating back through your site. You should still aim to eliminate shifts on first load, but bfcache eligibility is a powerful tool for reducing their overall impact. This is particularly beneficial for common navigation patterns like returning to a search results page, a category listing, or a table of contents.
The rollout of bfcache in Chrome resulted in notable improvements to CLS metrics. While the bfcache is enabled by default in all major browsers, several site-specific factors can make a page ineligible for caching. Consult the bfcache guide to test your pages and identify any blockers that might prevent you from fully leveraging this feature.
Balancing CLS Improvements with Browser Allowances
The methods outlined in this guide provide various paths to identify and fix CLS issues. However, Core Web Vitals thresholds include built-in allowances, meaning you don't necessarily need to achieve a perfect score of zero. By applying the appropriate techniques, you can reduce the *impact* of layout shifts enough to stay within the "good" limits—ensuring a smoother and more polished experience for your users, even if minor shifts remain unavoidable in certain edge cases.



