Where CLS Shows Up in Real Projects
Cumulative Layout Shift (CLS) isn't just a metric on a dashboard—it's the jarring moment a user tries to tap a button and the page jumps. In real projects, CLS appears in predictable places, and understanding those patterns is the first step to fixing them.
Image-heavy content sites are a classic hotspot. When images load without explicit dimensions, the browser reserves zero space. Once the image arrives, the layout shifts everything below it. A typical news article with multiple embedded images can accumulate a CLS score of 0.3 or higher—enough to frustrate readers and hurt search rankings. The fix isn't complicated: always set width and height attributes on <img> tags, or use CSS aspect-ratio boxes. But teams often forget this on older content or third-party embeds.
Another common culprit is dynamic ad slots. Ad networks often inject banners of varying sizes after the page loads. If the container doesn't have a reserved space, the ad push causes a shift. One approach is to reserve a fixed-height placeholder based on the most common ad size, then let the ad fill it. However, if the ad is smaller or larger, you still see shifts. A better method is to use a container with min-height and allow overflow, but that can leave empty space. There's no perfect answer—only trade-offs.
Web fonts are a less obvious source of CLS. When a fallback font renders first and the custom font loads later, the text block can change size and shift. The solution is to use font-display: swap with careful sizing of fallback fonts, or preload the font to reduce the swap delay. Many teams overlook this because the shift is small, but on a page with many text blocks, the cumulative effect adds up.
Third-party widgets—like social media feeds, maps, or chat widgets—are another frequent offender. These scripts often load late and inject elements that push existing content. The best practice is to load them in a dedicated container with a known height, or defer them to after the main content is stable. If the widget's height is unpredictable, consider using a placeholder that matches the average height and accept minor shifts on edge cases.
Finally, single-page applications (SPAs) have their own CLS challenges. Route changes that fetch data asynchronously can cause layout shifts if the new content is taller or shorter than the old. Frameworks like React or Vue can help by using skeleton screens or fixed-height containers during loading, but it requires discipline across the team.
In summary, CLS shows up wherever content loads asynchronously without reserved space. The key is to audit your site with a CLS-focused tool, like Lighthouse or the Web Vitals extension, and address each source systematically. Start with images and ads—they give the biggest wins—then tackle fonts and third-party scripts.
Foundations Readers Confuse
Many web professionals misunderstand the root causes of CLS. Let's clear up some common confusions.
CLS Is Not Just About Images
While images are a major contributor, CLS can be caused by any element that changes size or position after the initial render. This includes videos, iframes, ads, embeds, and even text reflow from web fonts. Teams that focus only on images often miss shifts from other sources.
Setting Width and Height Is Not Enough
It's true that setting dimensions on images is critical, but it's not a silver bullet. For responsive images, using width: 100% without a height can still cause shifts if the aspect ratio isn't maintained. The modern approach is to use aspect-ratio in CSS or the width and height attributes combined with max-width: 100%. Also, if you lazy-load images with JavaScript, the placeholder must have the correct intrinsic size.
Dynamic Content Can Be Predicted
Some developers think dynamic content—like user-generated comments or real-time updates—makes CLS unavoidable. But you can reserve space based on expected content size or use a fixed-height container with overflow scrolling. For example, a comment section can have a min-height that matches the average load, and new comments can append without shifting the page if the container is already sized.
CLS Is a Mobile-First Problem
Mobile devices have smaller viewports, so any shift is more disruptive. But CLS affects desktop too, especially when users resize the browser or when content loads in sidebars. Don't ignore desktop; just prioritize mobile fixes.
CLS Can Be Caused by CSS Animations
Animations that change layout properties—like width, height, margin, or top—can trigger CLS if they happen after the page has loaded. Use transform and opacity for animations instead, as they don't affect layout.
Understanding these foundations helps teams avoid chasing the wrong fixes. The goal is to stabilize the layout before any content loads, then only add content in reserved spaces.
Patterns That Usually Work
Over time, several patterns have proven reliable for preventing CLS. Here are the ones we recommend most.
Reserve Space with Explicit Dimensions
For every image, video, or iframe, set width and height in the HTML or CSS. For responsive images, use srcset with sizes and let the browser pick the right size. Combine with aspect-ratio to handle unknown widths. Example: <img src='photo.jpg' width='800' height='600' alt='' style='max-width: 100%; height: auto;' />.
Use Skeleton Screens for Dynamic Content
When content loads asynchronously (e.g., search results, user profiles), show a placeholder that matches the final layout shape. Skeleton screens reduce perceived load time and prevent shifts because the space is already reserved. This works well for lists, cards, and tables.
Preload Key Resources
Preloading fonts, hero images, and above-the-fold content ensures they load early, reducing the chance of late shifts. Use <link rel='preload'> for fonts and critical images. For fonts, also set font-display: swap to show fallback text immediately and swap later without shifting if the new font is the same size.
Set Fixed Heights for Ad Slots
Ad containers should have a min-height equal to the most common ad size (e.g., 250px for a medium rectangle). If the ad is smaller, the container shows empty space; if larger, the ad may overflow or be clipped. Accept this trade-off or use a more sophisticated approach like dynamic resizing with a fixed container.
Defer Non-Critical JavaScript
Third-party scripts that modify the DOM should be deferred until after the main content is stable. Use async or defer attributes, and load them in a container with reserved space. For scripts that inject elements, ensure the container has a defined height.
These patterns work because they control the layout before content arrives. The key is consistency—apply them across the entire site, not just on new pages.
Anti-Patterns and Why Teams Revert
Even with good intentions, teams often fall into traps that undo their CLS efforts. Here are the most common anti-patterns.
Relying on JavaScript for Layout
Some teams use JavaScript to set image dimensions after load, thinking it's easier than hardcoding. This creates a flash of unlaid-out content, then a shift when the script runs. Always set dimensions in HTML or CSS; JavaScript should only enhance, not define, layout.
Using Percentage-Based Heights
Setting height: 100% on a container can cause shifts if the parent's height is not defined. Instead, use aspect-ratio or fixed heights for elements that need to hold space.
Over-Optimizing for Speed at the Expense of Stability
Lazy-loading everything—images, ads, even above-the-fold content—can cause multiple shifts as each element loads. Reserve space for lazy-loaded elements or use eager loading for critical content.
Ignoring the Cumulative Part of CLS
Teams sometimes fix one big shift but ignore many small shifts that add up. For example, a page might have a single shift from an ad (0.1) and ten tiny shifts from font swaps (0.01 each), totaling 0.2. Address all sources, not just the biggest.
Not Testing on Real Devices
Simulated CLS scores in Lighthouse don't always match real user experience. Test on actual mobile devices with slow connections to catch shifts that lab tests miss. Also monitor field data from Chrome User Experience Report (CrUX).
Teams revert to these anti-patterns because they seem simpler or faster. But the short-term gain leads to long-term pain. The discipline of reserving space upfront pays off.
Maintenance, Drift, and Long-Term Costs
CLS prevention isn't a one-time fix—it requires ongoing attention. Over time, teams add new features, update libraries, and change layouts, each time risking a regression.
Regular Audits
Schedule monthly CLS audits using Lighthouse or a custom script. Check both lab data and field data. Create a dashboard that tracks CLS over time so you spot drifts early.
Code Reviews and Guidelines
Include CLS checks in code reviews. For example, require that every new image has width and height attributes, and every new dynamic component has a reserved space. Document these guidelines in a shared wiki.
Third-Party Scripts Change
Ad networks and widget providers update their code, sometimes breaking your layout. Monitor third-party scripts for changes and test in a staging environment before pushing to production. Consider using a tag manager with version control.
Team Turnover
When new developers join, they may not know the CLS rules. Onboarding should include a session on web vitals and the site's specific patterns. Pair new hires with experienced team members for their first few tasks.
The long-term cost of ignoring CLS is user frustration, lower search rankings, and higher bounce rates. The maintenance cost is relatively low if you build good habits from the start.
When Not to Use This Approach
While the patterns above work for most sites, there are cases where a different strategy is needed.
Extremely Dynamic Content
If your site displays user-generated content with unpredictable sizes—like a live feed of images of varying dimensions—reserving exact space is impossible. In that case, use a fixed-size container with overflow hidden or scroll, and accept some content being cut off. Alternatively, use a masonry layout that doesn't shift existing content but adds new items in available gaps.
Single-Page Apps with Complex Routing
SPAs that change route without a full page load can still experience CLS if the new view is taller or shorter. Instead of reserving space for every possible view, use a transition that fades or slides, and set a minimum height for the main content area. This prevents the page from jumping when the route changes.
When CLS Is Not the Priority
If your site has extremely low traffic or is a prototype, spending weeks on CLS may not be the best use of time. Focus on critical user journeys first. But if your site is public and you care about SEO, CLS is worth addressing.
In short, these methods are for sites where layout stability is a priority and where most content can be predicted. For edge cases, adapt the principles rather than force-fitting them.
Open Questions and FAQ
Here we answer common questions about CLS fixes and address lingering uncertainties.
Does CLS affect SEO?
Yes, CLS is part of Google's Core Web Vitals, which are ranking signals. A poor CLS score can hurt your search visibility. However, it's one of many factors—a good CLS score doesn't guarantee top rankings, but a bad one can hold you back.
What is a good CLS score?
Google considers a CLS score less than 0.1 as good, between 0.1 and 0.25 as needs improvement, and above 0.25 as poor. Aim for under 0.1 for the 75th percentile of page loads.
Can I fix CLS without a developer?
Some fixes require code changes, but you can use plugins for CMS platforms (like WordPress) that automatically set image dimensions and add placeholders. However, for custom sites, developer involvement is usually needed.
How do I measure CLS accurately?
Use the web-vitals library in the browser, or tools like Lighthouse, PageSpeed Insights, and the Chrome User Experience Report. Field data (CrUX) is more reliable than lab data.
What if I can't avoid a shift?
If a shift is unavoidable, minimize its impact. For example, if an ad must load late, place it near the bottom of the viewport where shifts are less disruptive. Also, set a min-height on the container to reduce the shift distance.
CLS is a solvable problem. Start with the high-impact fixes, monitor your progress, and iterate. Your users will thank you.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!