Web Performance

Fix CLS Dynamic Content: Eliminate Layout Shift for Better UX & SEO

Cumulative Layout Shift (CLS) can silently degrade user experience and tank your search rankings. This guide dives deep into diagnosing and eliminating CLS caused by dynamically injected content, ads, and iframes, providing actionable strategies and code examples to achieve stable, high-performing web applications.

Krapton Engineering
Reviewed by a senior engineer12 min read
Share
Fix CLS Dynamic Content: Eliminate Layout Shift for Better UX & SEO

In 2026, a stable and predictable user interface isn't just a nicety; it's a critical component of user experience and a direct factor in your site's search engine ranking. Cumulative Layout Shift (CLS), a Core Web Vitals metric, measures the unexpected movement of visual page content. When ads, images, or other dynamic elements load late and push existing content around, it frustrates users, leads to misclicks, and signals to Google that your page offers a poor experience.

TL;DR: Cumulative Layout Shift (CLS) negatively impacts user experience and SEO. To fix CLS dynamic content, reserve space for images, ads, and iframes using CSS `aspect-ratio` or explicit dimensions, optimize font loading with `font-display: optional`, and ensure dynamically injected content doesn't shift existing elements. Verify fixes with PageSpeed Insights and CrUX data.

Key takeaways

Close-up of a mechanic working on an engine, showcasing expertise and focus in an auto repair shop.
Photo by Bulat843 🌙 on Pexels
  • CLS is a critical Core Web Vital: It measures visual stability and directly impacts Google search rankings and user satisfaction.
  • Dynamic content is a primary culprit: Late-loading images, ads, embeds, and fonts frequently cause unexpected layout shifts.
  • Proactive space reservation is key: Use CSS `aspect-ratio`, explicit `width`/`height` attributes, or `min-height` on containers to prevent shifts.
  • Optimize font loading: Employ `font-display: optional` or `swap` with `size-adjust` to mitigate Flash of Unstyled/Invisible Text (FOUT/FOIT).
  • Verify with real-user data: While Lighthouse is useful, always confirm CLS improvements with CrUX field data in PageSpeed Insights and Google Search Console.

What is Cumulative Layout Shift (CLS) and Why it Matters in 2026

Close-up of colorful source code on a monitor, showcasing programming and technology concepts.
Photo by Abdul Kayum on Pexels

Cumulative Layout Shift (CLS) quantifies how much unexpected layout shift occurs on a page. It's a critical Core Web Vital metric, alongside Largest Contentful Paint (LCP) and Interaction to Next Paint (INP), that Google uses as part of its Page Experience signal for ranking websites. A high CLS score indicates a frustrating user experience where content jumps around, often leading to misclicks, disorientation, and abandonment.

For businesses, this isn't just an aesthetic problem. A poor CLS score can directly impact conversion rates, reduce time on site, and, crucially, lower your visibility in search results. Google's algorithms prioritize pages that offer a stable, predictable, and delightful user experience, and CLS is a direct measure of that stability. Achieving a CLS score of 0.1 or less is considered 'Good' by Google, while scores above 0.25 are 'Poor'.

Diagnosing CLS: Field Data vs. Lab Data

Understanding your CLS score requires looking at both field data (Real User Monitoring, RUM) and lab data. Lab data, gathered in controlled environments like Lighthouse, provides reproducible insights into potential issues. However, field data from the Chrome User Experience Report (CrUX) reflects what real users experience, encompassing various network conditions, devices, and interactions. Google's ranking signals are primarily based on CrUX field data.

PageSpeed Insights is your go-to tool for a quick overview, showing both lab (Lighthouse) and field (CrUX) data. For deeper diagnostics, Chrome DevTools is invaluable. Open the Performance panel, record a page load, and look for the 'Layout Shifts' track. Enabling 'Layout Shift Regions' in the Rendering tab visually highlights areas that have shifted, making it easier to pinpoint culprits.

For continuous monitoring, integrating a RUM solution that captures Core Web Vitals is essential. Libraries like `web-vitals.js` can push CLS data to your analytics platform, giving you real-time insights into user experience across your entire user base. Our team often implements custom `PerformanceObserver` instances to capture and report these metrics reliably:

import { getCLS } from 'web-vitals';

function sendToAnalytics(metric) {
  // Replace with your actual analytics sending logic
  console.log('CLS metric:', metric);
}

// Report CLS to your analytics endpoint
getCLS(sendToAnalytics);

// For advanced debugging, observe all layout shifts
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.entryType === 'layout-shift') {
      // Log details of each individual shift
      // console.log('Layout Shift:', entry);
    }
  }
});
observer.observe({ type: 'layout-shift', buffered: true });

Common Causes of CLS from Dynamic Content

Many web applications today rely heavily on dynamic content loading, which, if not handled carefully, becomes a major source of CLS. Understanding these common patterns is the first step to effective remediation.

Images Without Dimensions

This is perhaps the most classic cause of CLS. When an `` tag is rendered without explicit `width` and `height` attributes (or equivalent CSS `width`/`height`), the browser initially doesn't know how much space to reserve. When the image eventually loads, it pushes down any content below it, causing a significant layout shift. Modern practices, especially with frameworks like Next.js, advocate for components like `` which automatically handle dimension reservation and lazy loading.

Dynamically Injected Ads and Embeds

Third-party content, such as advertisements, social media embeds (Twitter, Instagram), and video players (YouTube, Vimeo), are notorious for causing CLS. These elements often load asynchronously and inject themselves into the DOM without prior space reservation. Ad networks, in particular, can serve varying ad sizes, making it challenging to predict the exact dimensions needed. This often results in a 'jump' as the ad slot expands to accommodate the creative.

In a recent client engagement, we observed a persistent CLS issue on an e-commerce product page, primarily driven by dynamically loaded recommendation widgets from a third-party vendor. Initially, the team tried to fix CLS dynamic content by simply wrapping the widget in a `div` with a `min-height`, but because the widget's actual content had varying heights, this led to either excessive blank space or continued shifts. We eventually implemented an IntersectionObserver to only load the widget when it was near the viewport, combined with a dynamically calculated `min-height` based on the most common widget height, significantly reducing the initial layout shift.

Web Fonts Causing FOIT/FOUT

Fonts are another subtle but powerful source of CLS. When custom web fonts are downloaded, the browser might initially render text using a fallback font (Flash of Unstyled Text, FOUT) or hide the text entirely (Flash of Invisible Text, FOIT). Once the custom font loads, the text reflows, often changing its size, weight, and spacing, leading to layout shifts. The CSS `font-display` property is crucial for controlling this behavior.

Content Injected Above Existing Content

This often occurs with cookie consent banners, promotional pop-ups, or notification messages that appear at the top of the page after the initial render. If these elements are not positioned carefully (e.g., using `position: fixed` or `position: sticky` to overlay content rather than push it), they will force all subsequent content downwards, incurring a CLS penalty.

Step-by-Step Fixes for Eliminating CLS

Fixing CLS dynamic content requires a systematic approach, focusing on proactive space reservation and careful handling of asynchronous content.

1. Reserve Space for All Media & Embeds

The most effective strategy is to tell the browser exactly how much space an element will occupy before it loads.

  • Images and Videos: Always include `width` and `height` attributes on your `` and `
/* For a 16:9 aspect ratio */
.responsive-image {
  width: 100%; /* Or any desired width */
  aspect-ratio: 16 / 9;
  height: auto; /* Ensure height adjusts based on aspect-ratio */
}

/* For iframes or fixed aspect ratio containers */
.video-container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 aspect ratio (9 / 16 * 100) */
  height: 0;
  overflow: hidden;
}
.video-container iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
  • Ads and Embeds: For third-party content where you can't control the HTML directly, wrap them in a container with a defined `min-height` and `min-width`. If ad sizes vary, reserve space for the largest common ad size to minimize shifts. You might also use a skeleton loader or a placeholder with the reserved dimensions.

2. Optimize Web Font Loading

Control how fonts load to prevent layout shifts:

  • `font-display` Property: Use `font-display: optional` in your `@font-face` rules. This tells the browser to use a fallback font if the custom font isn't available quickly, eliminating CLS at the cost of potentially not using the custom font on slow connections. If you must use the custom font, `font-display: swap` is a good compromise, showing a fallback and then swapping once the custom font loads.
  • Preload Critical Fonts: Use `` for fonts essential to your initial render. This tells the browser to fetch them with high priority.
  • `size-adjust` for `font-display: swap`: When using `font-display: swap`, you can use CSS `size-adjust` in conjunction with `@font-face` to ensure the fallback font closely matches the dimensions of your custom font, minimizing the visual jump.
@font-face {
  font-family: 'KraptonSans';
  src: url('/fonts/KraptonSans-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: optional; /* Best for CLS */
}

/* Example with size-adjust for 'swap' */
@font-face {
  font-family: 'KraptonDisplay';
  src: url('/fonts/KraptonDisplay-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
  /* Adjust fallback font size to match KraptonDisplay more closely */
  /* Example: If KraptonDisplay is 1.1x larger than system-ui */
  size-adjust: 110%;
  ascent-override: 90%;
  descent-override: 20%;
  line-gap-override: 10%;
}

3. Handle Dynamically Injected Content Gracefully

For content that must load asynchronously and might change dimensions, plan ahead:

  • Use `transform` for Animations: If you need to animate elements, use CSS `transform` properties (`translate`, `scale`) instead of `width`, `height`, or `top`/`left`. `transform` doesn't trigger layout changes, only painting.
  • Pre-allocate Space for Ad Slots: Coordinate with your ad provider to understand the typical dimensions of ads served. Create empty `div` containers with these dimensions (`min-height`, `min-width`) to hold the ads, preventing shifts when they finally render.
  • Position Overlays Carefully: Use `position: fixed` or `position: sticky` for elements like cookie banners or pop-ups that should overlay content rather than pushing it. This ensures they don't contribute to CLS.

When NOT to use this approach

While reserving space is generally beneficial, blindly applying `min-height` to every dynamic container can lead to excessive blank space on your page, especially if the content fails to load or loads in a much smaller variant. Over-optimization in this area might create a visually sparse page, which can also degrade user experience. For highly variable content, a more dynamic approach using JavaScript to measure and set placeholder heights *before* content loads (if possible) or carefully observing `MutationObserver` events might be necessary, though this adds complexity. Always balance CLS reduction with aesthetic appeal and content availability.

Verifying Your CLS Fixes and Measuring Impact

After implementing fixes, verification is crucial. Start with Chrome DevTools and Lighthouse for immediate feedback. Run a Lighthouse audit (in Incognito mode to avoid extensions) and check the 'Performance' score and the 'Diagnostics' section for 'Avoid enormous network payloads' or 'Ensure text remains visible during webfont load'.

Next, use PageSpeed Insights. Re-running the audit will give you updated lab data. For CrUX field data, however, you'll need to wait. Google's CrUX data is collected over a 28-day rolling window, so significant improvements might take a few weeks to reflect. Monitor your Google Search Console Core Web Vitals report for aggregate trends.

Our team measured a significant impact on a client's marketing landing pages. By systematically addressing image dimensions, preloading critical fonts, and reserving space for dynamically injected A/B test variations, we reduced their average CLS from a 'Poor' 0.25 to a 'Good' 0.01 across key pages. This improvement not only led to a noticeable uplift in user engagement metrics but also contributed to improved organic search visibility for their target keywords, demonstrating the clear ROI of focusing on web performance.

Krapton's Approach to Core Web Vitals Optimization

At Krapton, our engineering team approaches Core Web Vitals optimization, including tackling complex CLS issues, with a diagnostic-first mindset. We don't just apply generic fixes; we dive deep into your site's unique architecture and user behavior data.

Our process typically begins with a comprehensive audit using a combination of synthetic testing tools like WebPageTest and real-user monitoring (RUM) platforms. We analyze CrUX data, debug layout shifts in Chrome DevTools, and identify the root causes specific to your application's dynamic content, third-party scripts, and custom font loading strategies. Whether you're running a high-traffic e-commerce platform on Next.js or a complex SaaS application, our experts tailor solutions to your stack. We have extensive experience optimizing performance for applications built with React, Next.js, and other modern web technologies, ensuring that the fixes are robust and maintainable.

Here's a comparison of common CLS debugging tools our engineers leverage:

ToolData TypeStrengthsLimitations
PageSpeed InsightsLab & FieldQuick overview, official Google data (CrUX), actionable recommendations.Field data is 28-day aggregate, no real-time debugging.
Chrome DevToolsLabReal-time, deep dive into individual layout shifts, visual debugging (Layout Shift Regions).Lab data only, requires manual testing, not scalable for all pages.
WebPageTestLabDetailed waterfall charts, filmstrip view, repeatable tests from various locations/devices.Lab data only, complex interface for beginners.
RUM (e.g., Sentry, Datadog)FieldReal-user experience, aggregate data across all users, custom dashboards, alerts.Setup required, data aggregation can mask individual issues without drilling down.

We believe in building for speed and stability from the ground up. Our comprehensive website development services ensure that Core Web Vitals are a priority throughout the development lifecycle, not just an afterthought. For clients leveraging specific frameworks, our hire Next.js developers program provides access to engineers deeply skilled in framework-specific optimizations to fix CLS dynamic content.

FAQ

How often should I check my CLS score?

You should monitor your CLS score regularly, ideally through a RUM solution that provides daily or weekly trends. For major site updates or new feature rollouts, perform immediate Lighthouse audits and recheck PageSpeed Insights after a few weeks for updated CrUX data.

Can JavaScript cause CLS?

Yes, JavaScript is a common cause of CLS, especially when it dynamically injects content, modifies DOM elements without reserving space, or triggers animations that change element dimensions rather than using `transform` properties. Asynchronous loading of third-party scripts is a frequent culprit.

What is a good CLS score?

According to Google, a 'Good' CLS score is 0.1 or less. A score between 0.1 and 0.25 is 'Needs Improvement,' and anything above 0.25 is considered 'Poor,' indicating a significant negative impact on user experience and potential SEO penalties.

Does lazy loading contribute to CLS?

Lazy loading can contribute to CLS if not implemented correctly. If a lazy-loaded image or iframe doesn't have its dimensions reserved (via `width`/`height` attributes or `aspect-ratio` CSS), it will cause a layout shift when it eventually loads and renders. Proper lazy loading requires pre-allocating space.

Ready to Eliminate Your CLS Bottlenecks?

Don't let Cumulative Layout Shift hinder your user experience or damage your search rankings. Krapton's expert engineering team can help you diagnose, fix CLS dynamic content, and implement robust web performance strategies for lasting stability and speed. Run a free SEO audit with Krapton's SEO Analyzer to understand your current Core Web Vitals performance and identify actionable improvements.

About the author

Krapton Engineering is a team of principal-level software engineers and performance specialists with years of hands-on experience shipping high-scale web and mobile applications for startups and enterprises. We specialize in optimizing Core Web Vitals, building resilient architectures with Next.js and React Native, and integrating advanced AI solutions to deliver exceptional digital products worldwide.

core web vitalsweb performanceCLSlayout shiftpage speedSEO performancenext.js performancedynamic contentiframesfont optimization
About the author

Krapton Engineering

Krapton Engineering is a team of principal-level software engineers and performance specialists with years of hands-on experience shipping high-scale web and mobile applications for startups and enterprises. We specialize in optimizing Core Web Vitals, building resilient architectures with Next.js and React Native, and integrating advanced AI solutions to deliver exceptional digital products worldwide.