The common belief is that many small layout shifts are less damaging to your CLS score than one large shift. In absolute terms, this is technically true — ten 0.01 shifts produce a lower maximum session window score than one 0.15 shift. But the session window algorithm means those ten small shifts can cluster within the same window and produce a combined score that exceeds the 0.1 “good” threshold, which is how sites with no single large shift still fail CLS. Understanding the session window mechanism is essential for diagnosing CLS failures that appear to have no obvious large-shift culprit.
The Session Window Algorithm With 1-Second Gap and 5-Second Cap
CLS does not sum all layout shifts across the entire page lifecycle. The Chrome Speed Metrics Team finalized the current algorithm after extensive research into alternatives that would fairly measure layout stability for both traditional multi-page sites and single-page applications. The previous approach — summing all shifts for the entire page duration — produced massive CLS scores for SPAs where users remained on a single page for extended sessions, creating an unfair measurement disadvantage.
The current algorithm groups shifts into session windows. A session window begins with the first layout shift and includes all subsequent shifts that occur within 1 second of the previous shift in that window. The window is capped at 5 seconds total duration regardless of how frequently shifts occur within it. The page’s reported CLS score is the maximum session window score across all windows during the page’s lifetime — not the sum of all windows and not the average.
How Multiple Windows Produce the Final CLS Score
This means a page with one bad 5-second burst of shifts and twenty clean minutes of user interaction reports only the worst window’s score. The algorithm is deliberately forgiving of isolated small shifts separated by time, but it penalizes concentrated bursts of instability where the user experiences rapid successive movement.
Each individual layout shift score is calculated as the product of two measurements: the impact fraction (the combined visible area of all unstable elements in both the current and previous frames, divided by the viewport area) and the distance fraction (the greatest distance any unstable element moved, divided by the viewport’s largest dimension). These per-shift scores are summed within each session window to produce the window score. Google defines a CLS score of 0.1 or less as “good” and above 0.25 as “poor.”
The 70/30 split reported by web.dev when the algorithm changed is worth noting: 70% of origins saw no change at the 75th percentile, and the remaining 30% saw improvement. The algorithm change specifically helped long-lived pages (SPAs, dashboards, media players) without weakening measurement for traditional page loads.
How Small Shifts Accumulate Within a Single Window
When multiple small shifts occur in rapid succession — as happens during ad loading, web font swapping, or dynamic content injection — they group into the same session window because each shift occurs within 1 second of the previous one. The individual shifts may appear negligible when examined in isolation, but the session window algorithm treats the burst as a single unit of instability.
Consider a concrete scenario: a page loads a hero image without reserved dimensions (shift of 0.02), then a web font swaps and reflows a heading (shift of 0.03), then an ad container above the fold initializes with zero height before receiving creative dimensions (shift of 0.04), then a cookie consent banner slides in from the bottom and pushes content up (shift of 0.03). All four events fire within 2 seconds of each other. Each individual shift is well below the 0.1 threshold. But the session window containing all four produces a combined score of 0.12, which fails the “good” threshold.
This accumulation pattern is the primary reason complex pages with ads, dynamic widgets, and web fonts fail CLS despite having no single element that produces a large shift. The shifts come from different sources, are owned by different teams (engineering, ad ops, design), and appear harmless in isolation. Only the session window aggregation reveals the cumulative impact.
The timing of shifts relative to each other is the critical variable. If the same four shifts occurred with gaps greater than 1 second between each pair, they would create four separate session windows of 0.02, 0.03, 0.04, and 0.03 respectively. The maximum window score would be 0.04 — well within the “good” range. The total instability is identical, but the temporal distribution changes the score dramatically.
Why a Single Large Shift Can Produce a Lower Score Than Expected
The session window algorithm’s maximum-window-score approach means that the distribution of shift timing can produce counterintuitive results when comparing single large shifts against distributed smaller shifts.
A single layout shift of 0.12 creates a session window containing only that shift. The window score is 0.12 — above the 0.1 threshold, and the page fails CLS. This is straightforward.
But if the same 0.12 total instability were distributed as two shifts of 0.06 separated by more than 1 second of inactivity, they would create two separate session windows of 0.06 each. The maximum window score would be 0.06, and the page passes CLS. The total layout instability experienced by the user is identical — 0.12 worth of element movement — but the metric treats the temporally separated version as less severe.
This is an intentional design decision, not a measurement flaw. The Chrome team’s research indicated that rapid successive shifts are more disorienting to users than shifts separated by time. A user can re-orient visually between shifts that have a gap, but a burst of rapid movement creates a perception of the page being fundamentally unstable. The session window algorithm encodes this perceptual difference.
The practical implication is that a site can potentially improve its CLS score without reducing the total amount of layout shift, simply by introducing temporal spacing between shift-causing events. An ad container that initializes 1.5 seconds after a font swap creates two separate windows rather than one combined window. This is not a trick — it genuinely reduces the perceptual instability experienced by users.
Layout Shift Attribution Tools and Per-Element Diagnosis
Chrome DevTools’ Performance panel and the Layout Instability API both report individual shifts with timestamps, but neither automatically groups them into session windows. The diagnostic task requires either manual grouping or instrumentation that performs the grouping algorithmically.
The web-vitals JavaScript library’s attribution build automates this process. It reports the CLS score along with the specific LayoutShift entries that composed the worst session window, including each shift’s timestamp, score, and the sources property identifying which DOM elements moved. This attribution data is essential because the worst session window often contains shifts from 3-5 different sources that coincidentally fired within the same second, making the root cause appear multi-factorial when examined without temporal context.
The diagnostic workflow proceeds in three steps. First, identify the worst session window’s time range and total score from the web-vitals attribution data. Second, examine the individual shifts within that window using the LayoutShift.sources property, which reports up to five DOM nodes per shift that moved or were added. Third, trace each shifted element back to its triggering event — ad fill, font swap, image load, dynamic content injection, or animation.
In DevTools, the Experience row in the Performance panel marks layout shifts visually on the timeline. Recording a performance trace during page load and scrolling reveals shift clusters. Enabling the “Layout Shift Regions” checkbox highlights the shifted elements as colored overlays on the page, providing immediate visual identification of which elements moved.
Practical Optimization Limits and Diminishing Returns on CLS Fixes
For field data at scale, deploying the PerformanceObserver for layout-shift entries with buffered: true captures all shifts from page load through session end. Logging each shift’s timestamp, score, and sources property to a RUM endpoint creates the dataset needed to identify which session windows fail and which element combinations compose them across the full user population.
Eliminating every small layout shift is impractical on complex pages with ads, dynamic content, and third-party widgets. The effective strategy targets the worst session window specifically rather than attempting to achieve zero CLS site-wide.
Two approaches reduce the worst window’s score. The first is reducing individual shift magnitude within the window — reserving explicit dimensions for ad containers, applying font metric overrides to prevent font-swap shifts, and setting width/height attributes on images. Each reduction in per-shift score directly reduces the window total.
The second approach is temporal separation — introducing timing gaps greater than 1 second between sequential shift-causing events to split them into separate session windows. If an ad container initializes at t=1.0s and a font swap occurs at t=1.5s, they share a window. Delaying the ad initialization to t=3.0s splits them into separate windows. This strategy reduces CLS without eliminating any individual shift source, which is sometimes the only viable approach when shift sources are third-party controlled and their individual shift magnitudes cannot be reduced.
The 5-second cap provides a natural ceiling on window accumulation — even if shifts fire continuously, the window closes after 5 seconds and a new window begins. For pages with sustained shift activity (real-time dashboards, live feeds), this cap prevents indefinite accumulation, though the per-window score during those 5 seconds can still exceed the threshold if shifts are frequent and large.
Does user-initiated interaction reset the CLS session window counter?
No. User interactions such as clicks, taps, or keyboard input exclude the resulting layout shifts from CLS scoring for 500ms after the input event. However, the session window mechanism itself continues independently. Shifts that occur outside the 500ms exclusion window after an interaction still accumulate into the current or next session window. The exclusion applies per shift, not per window.
Are layout shifts from browser resize or device orientation change counted in CLS?
No. CLS excludes shifts triggered by viewport size changes, including browser window resizing and device orientation rotation. The specification filters these events because they represent expected reflows that users initiated. Only shifts that occur at a stable viewport size count toward the session window score. This exclusion prevents responsive layout recalculations from inflating CLS during normal browsing behavior.
Does CLS scoring differ between Chrome on desktop and Chrome on Android?
The scoring algorithm is identical across platforms. However, field CLS scores often diverge because mobile devices encounter more dynamic content injection from ad networks, slower font loading that triggers swap shifts, and viewport-dependent layout changes that desktop viewports do not trigger. The session window mechanism operates the same way, but the shift events feeding into it differ by platform and device capability.