Technical

Cumulative Layout Shift (CLS)

A Core Web Vitals metric that measures the sum of all unexpected layout shift scores that occur throughout the entire lifespan of a page, quantifying visual instability.

Quick Answer

  • What it is: A Core Web Vitals metric that measures the sum of all unexpected layout shift scores that occur throughout the entire lifespan of a page, quantifying visual instability.
  • Why it matters: CLS prevents frustrating experiences where content moves unexpectedly, causing misclicks and poor user experience.
  • How to check or improve: Reserve space for dynamic content, avoid inserting content above existing content, and use CSS transforms for animations.

When you'd use this

CLS prevents frustrating experiences where content moves unexpectedly, causing misclicks and poor user experience.

Example scenario

Hypothetical scenario (not a real company)

A team might use Cumulative Layout Shift (CLS) when Reserve space for dynamic content, avoid inserting content above existing content, and use CSS transforms for animations.

Common mistakes

  • Confusing Cumulative Layout Shift (CLS) with Core Web Vitals: A set of three specific metrics that Google uses to measure user experience on websites: loading performance (LCP), interactivity (INP), and visual stability (CLS). Learn how to measure and improve your Core Web Vitals scores.
  • Confusing Cumulative Layout Shift (CLS) with Largest Contentful Paint (LCP): A Core Web Vitals metric that measures the render time of the largest image or text block visible within the viewport, relative to when the page first started loading.
  • Confusing Cumulative Layout Shift (CLS) with First Input Delay (FID): A Core Web Vitals metric that measures the time from when a user first interacts with a page to the time when the browser is able to begin processing event handlers in response.

How to measure or implement

  • Reserve space for dynamic content, avoid inserting content above existing content, and use CSS transforms for animations

Check your site's layout stability

Start here
Updated Jan 20, 2026·7 min read

Cumulative Layout Shift (CLS) is a Core Web Vitals metric that quantifies how much unexpected movement occurs on a page as it loads and throughout its lifecycle. Unlike LCP and FID which measure speed and responsiveness, CLS measures visual stability—ensuring that page elements don't jump around and cause users to misclick or lose their reading position.

What is Cumulative Layout Shift?

CLS measures the sum of all individual layout shift scores for every unexpected layout shift that occurs during the entire lifespan of the page. A layout shift happens when a visible element changes its position from one frame to the next, causing content to move unexpectedly.

The CLS score is calculated using two measures:

  1. Impact fraction: The viewport area affected by unstable elements
  2. Distance fraction: The distance unstable elements have moved

The formula is: Layout Shift Score = Impact Fraction × Distance Fraction

Google's thresholds for CLS are:

  • Good: 0.1 or less
  • Needs Improvement: 0.1 to 0.25
  • Poor: More than 0.25

Note that CLS is unitless—it's not measured in seconds or pixels, but as a score representing the overall instability of the page.

Why CLS Matters for User Experience

The Frustration of Shifting Content

Layout shifts create several frustrating user experiences:

Misclicks and Mistaps: Users attempt to click a link or button, but content shifts at the last moment, causing them to click something else entirely. This is especially problematic with:

  • Ad placements that shift content
  • Late-loading images pushing text down
  • Dynamic content insertion
  • Banner notifications appearing

Lost Reading Position: Users lose their place while reading when content jumps. This forces them to scan the page to find where they were, disrupting engagement and comprehension.

Accidental Actions: Shifts can cause users to accidentally:

  • Submit forms prematurely
  • Navigate away from the page
  • Click on ads unintentionally
  • Delete or modify content
  • Make unintended purchases

SEO and Business Impact

CLS has been a Google ranking factor since June 2021 as part of Core Web Vitals. The impact extends beyond rankings:

User Engagement Metrics:

  • Sites with good CLS see 24% longer average session duration
  • 15% lower bounce rates compared to poor CLS
  • 12% more pages per session

Conversion Impact:

  • Yahoo! Japan improved CLS by 0.2 points and saw 15% more page views per session
  • NDTV improved CLS from 0.25 to 0.02 and reduced bounce rates by 50%
  • The Economic Times achieved 43% lower bounce rate after fixing CLS issues

Ad Revenue:

  • Better CLS scores lead to higher viewability scores
  • Reduced accidental clicks improve advertiser trust
  • Google Ad Manager considers CLS in quality scores

How CLS Works: Technical Deep Dive

Layout Shift Calculation

CLS calculation involves several components:

Impact Fraction The impact fraction is the union of the visible areas of all unstable elements for the previous frame and the current frame, as a fraction of the total viewport area.

Example: If an element occupies 50% of the viewport and moves down by 25% of the viewport height, the impact fraction combines both positions, potentially affecting 75% of the viewport.

Distance Fraction The distance fraction is the greatest distance any unstable element has moved in the frame (either horizontally or vertically) divided by the viewport's largest dimension (width or height).

Example: If an element moves 250px on a 1000px tall viewport, the distance fraction is 0.25.

Session Windows CLS is measured in session windows to better represent user experience:

  • Session windows close after 5 seconds with no shifts
  • Maximum session window duration is 5 seconds
  • New windows start with each layout shift
  • Only the maximum session window score is reported

Types of Layout Shifts

Expected vs Unexpected Shifts

Not all movement is bad. CLS only penalizes unexpected shifts:

Expected (not counted):

  • Shifts within 500ms of user input (click, tap, key press)
  • Animations using CSS transforms
  • Smooth transitions with CSS transitions
  • User-initiated scrolling

Unexpected (counted in CLS):

  • Content insertion without space reservation
  • Images/videos loading without dimensions
  • Fonts causing text reflow (FOIT/FOUT)
  • Dynamically injected content

Common Causes of Layout Shifts

Images Without Dimensions

<!-- Bad: No dimensions specified -->
<img src="hero.jpg" alt="Hero" />

<!-- Good: Dimensions reserved -->
<img src="hero.jpg" width="1200" height="600" alt="Hero" />

<!-- Better: With aspect-ratio -->
<img
  src="hero.jpg"
  width="1200"
  height="600"
  style="aspect-ratio: 2/1;"
  alt="Hero"
/>

Dynamic Content Injection

  • Ads loading and pushing content
  • Banners/alerts appearing at page top
  • Cookie consent notices
  • Related content widgets
  • Infinite scroll implementations

Web Fonts

  • Flash of Invisible Text (FOIT)
  • Flash of Unstyled Text (FOUT)
  • Different font metrics causing reflow

Responsive Design Issues

  • Different layouts at breakpoints
  • JavaScript-based responsive solutions
  • Viewport meta tag changes

Best Practices for Optimizing CLS

1. Always Include Size Attributes

Reserve space for all media elements:

<!-- Images -->
<img src="product.jpg" width="400" height="300" alt="Product" />

<!-- Responsive images with aspect ratio -->
<img
  src="product.jpg"
  width="400"
  height="300"
  sizes="(max-width: 600px) 100vw, 50vw"
  srcset="product-400.jpg 400w, product-800.jpg 800w"
  style="height: auto; max-width: 100%;"
  alt="Product"
/>

<!-- Videos -->
<video width="1920" height="1080" poster="poster.jpg">
  <source src="video.mp4" type="video/mp4" />
</video>

<!-- Iframes -->
<iframe src="embed.html" width="560" height="315"></iframe>

Use CSS aspect-ratio for modern browsers:

.responsive-iframe {
  aspect-ratio: 16 / 9;
  width: 100%;
  height: auto;
}

/* With fallback for older browsers */
.video-container {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
  height: 0;
}

.video-container iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

2. Reserve Space for Dynamic Content

Ad Slots

/* Reserve space for ads */
.ad-slot {
  min-height: 250px; /* Standard ad height */
  background: #f0f0f0; /* Neutral background */
}

/* Responsive ad container */
.ad-container {
  min-height: 90px;
}

@media (min-width: 768px) {
  .ad-container {
    min-height: 250px;
  }
}

Skeleton Screens

/* Skeleton for loading content */
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.skeleton-text {
  height: 20px;
  margin-bottom: 10px;
  border-radius: 4px;
}

3. Optimize Web Font Loading

Use font-display

@font-face {
  font-family: "CustomFont";
  src: url("font.woff2") format("woff2");
  font-display: optional; /* or 'swap' for critical text */
}

Preload Critical Fonts

<link
  rel="preload"
  href="/fonts/main.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

Match Font Metrics

/* Adjust fallback font to match custom font metrics */
@font-face {
  font-family: "Fallback";
  src: local("Arial");
  size-adjust: 105%; /* Adjust to match custom font */
  ascent-override: 90%;
  descent-override: normal;
  line-gap-override: normal;
}

body {
  font-family: "CustomFont", "Fallback", sans-serif;
}

4. Avoid Inserting Content Above Existing Content

Use Transforms Instead of Top/Left

/* Bad: Causes layout shift */
.banner {
  position: relative;
  top: -100px;
  transition: top 0.3s;
}

.banner.visible {
  top: 0;
}

/* Good: No layout shift */
.banner {
  transform: translateY(-100%);
  transition: transform 0.3s;
}

.banner.visible {
  transform: translateY(0);
}

Insert New Content Below the Fold

// Bad: Inserting at top
container.insertBefore(newContent, container.firstChild)

// Good: Appending at bottom or below viewport
container.appendChild(newContent)

// Or use intersection observer for below-fold insertion
const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadDynamicContent(entry.target)
      observer.unobserve(entry.target)
    }
  })
})

5. Handle Dynamic Content Carefully

Fixed Height Containers

/* Reserve space for dynamic content */
.comments-container {
  min-height: 500px;
  transition: min-height 0.3s ease;
}

.product-recommendations {
  height: 320px;
  overflow: hidden;
}

Progressive Enhancement

<!-- Baseline: Static content -->
<div class="static-content">
  <h2>Related Products</h2>
  <a href="/products">View All Products</a>
</div>

<!-- Enhanced: Dynamic loading -->
<script>
  if ("IntersectionObserver" in window) {
    // Load dynamic recommendations
    loadRecommendations()
  }
</script>

Common CLS Mistakes to Avoid

1. Lazy Loading Above-the-Fold Images

Never lazy load images that appear in the initial viewport:

<!-- Bad: Lazy loading hero image -->
<img src="hero.jpg" loading="lazy" alt="Hero" />

<!-- Good: Eager loading for above-fold -->
<img src="hero.jpg" loading="eager" width="1200" height="600" alt="Hero" />

<!-- Good: Lazy loading below-fold images -->
<img src="product.jpg" loading="lazy" width="400" height="300" alt="Product" />

2. Using JavaScript for Initial Layout

Avoid JavaScript-dependent layouts:

// Bad: Layout depends on JavaScript
window.addEventListener('load', () => {
  const header = document.querySelector('.header');
  header.style.height = calculateHeight() + 'px';
});

// Good: CSS-first approach with enhancement
.header {
  min-height: 80px; /* Baseline height */
}

3. Not Handling Responsive Images Properly

<!-- Bad: No consideration for aspect ratio changes -->
<picture>
  <source media="(min-width: 768px)" srcset="desktop.jpg" />
  <img src="mobile.jpg" alt="Hero" />
</picture>

<!-- Good: Consistent aspect ratios -->
<picture>
  <source
    media="(min-width: 768px)"
    srcset="desktop.jpg"
    width="1200"
    height="600"
  />
  <img src="mobile.jpg" width="600" height="300" alt="Hero" />
</picture>

4. Ignoring Third-Party Embeds

Social media embeds and widgets often cause shifts:

<!-- Bad: No space reservation -->
<div class="twitter-embed"></div>

<!-- Good: Reserved space with skeleton -->
<div class="twitter-embed" style="min-height: 500px;">
  <div class="embed-skeleton">Loading tweet...</div>
</div>

5. Animation Without Transform

/* Bad: Animating properties that trigger layout */
.slide {
  position: relative;
  animation: slide-in 0.3s;
}

@keyframes slide-in {
  from {
    left: -100%;
  }
  to {
    left: 0;
  }
}

/* Good: Using transform */
.slide {
  animation: slide-in 0.3s;
}

@keyframes slide-in {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0);
  }
}

Tools and Resources for Measuring CLS

Core Measurement Tools

Chrome DevTools

  • Performance panel shows layout shift regions
  • Rendering tab: Enable "Layout Shift Regions"
  • Console: Log CLS with Web Vitals library

PageSpeed Insights

  • Field data from real users (CrUX)
  • Lab data from Lighthouse
  • Specific elements causing shifts

WebPageTest

  • Filmstrip view showing shifts
  • Highlight layout shifts option
  • Frame-by-frame analysis

Debugging Tools

Layout Instability API

// Monitor layout shifts in real-time
new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    console.log("Layout shift:", entry)
    console.log("Score:", entry.value)
    console.log("Sources:", entry.sources)
  }
}).observe({ entryTypes: ["layout-shift"] })

Web Vitals Extension

  • Real-time CLS monitoring
  • Detailed shift attribution
  • Console logging of shifts

Monitoring Solutions

Google Search Console

  • Core Web Vitals report
  • Page-level CLS issues
  • Mobile vs desktop data

Rankwise CLS Monitor

  • Historical CLS tracking
  • Element-level attribution
  • Competitor comparisons

CLS Optimization by Content Type

E-commerce Product Pages

Critical areas for e-commerce:

  • Product image galleries
  • Price and availability updates
  • Customer reviews loading
  • Recommendation carousels
  • Size/variant selectors

Optimization strategies:

  • Use skeleton screens for product images
  • Reserve space for reviews section
  • Preload critical product images
  • Fixed heights for carousels

News and Publishing Sites

Common issues:

  • Ad slot insertions
  • Related article widgets
  • Social sharing buttons
  • Comment sections
  • Newsletter signup prompts

Solutions:

  • Fixed ad slot dimensions
  • Below-fold lazy loading
  • Static sharing buttons
  • Collapsed comments initially

Single Page Applications

SPA-specific challenges:

  • Route transitions
  • Component mounting/unmounting
  • State updates causing reflows
  • Virtual scrolling implementations

Best practices:

  • Use CSS transitions for route changes
  • Implement proper loading states
  • Avoid layout-dependent calculations
  • Test with real network conditions

Frequently Asked Questions

Why is my CLS different in lab vs field data?

Lab data (Lighthouse) measures CLS during page load only, while field data (CrUX) measures CLS throughout the entire page session. User interactions, scrolling, and dynamic content all affect field CLS but not lab measurements.

Can user interactions cause CLS?

Layout shifts within 500ms of user input (clicks, taps, key presses) are considered "expected" and don't count toward CLS. This includes expanding menus, accordions, and other interactive elements.

How do I fix CLS from ads?

Reserve space for ad slots with min-height CSS, use fallback content, implement fallbacks for unfilled slots, and consider using fixed ad positions rather than in-content placements.

Do CSS animations affect CLS?

CSS animations using transform and opacity don't cause layout shifts. Avoid animating properties like top, left, width, height, padding, or margin which trigger layout recalculation.

What's a good CLS score for different devices?

Aim for CLS under 0.1 on all devices. Mobile often has worse CLS due to smaller viewports and different ad sizes. Test thoroughly on real devices, not just browser emulation.

Put GEO into practice

Generate AI-optimized content that gets cited.

Try Rankwise Free
Newsletter

Stay ahead of AI search

Weekly insights on GEO and content optimization.