How we fixed CLS issues on the Spendesk marketing website
At Spendesk, we encountered performance issues on our marketing website that led us to discover how animation implementation choices can significantly impact both Core Web Vitals scores and actual performance. This case study demonstrates how a simple CSS change can solve multiple problems at once.
What is CLS?
Cumulative Layout Shift (CLS) is a Core Web Vital metric that measures visual stability by tracking unexpected layout shifts during page load. It quantifies how much visible content moves around as the page loads, with a score below 0.1 considered “good” by Google’s standards.
CLS issues typically occur when:
- Images load without reserved dimensions
- Content is dynamically inserted above existing content
- Fonts cause text reflow when they load
- Animations move elements in ways that affect surrounding content
Identifying the problem
Our journey began when we noticed our Core Web Vitals scores weren’t as strong as we wanted them to be. Using Google PageSpeed Insights, we discovered our homepage had a CLS score above the recommended threshold of 0.1.
To investigate further, we used webpagetest.org to perform a deep dive analysis. This tool provided a frame-by-frame breakdown of how our page loaded, highlighting exactly when and where shifts were being detected.
Isolating the culprit
After analyzing the test results, we identified our announcement banner as the component triggering the CLS warning. Interestingly, this appeared to be a false positive—the banner wasn’t actually causing visible layout shifts that pushed other content around. Instead, the animation itself was being flagged by the CLS detection algorithm.
Diagnosing the technical issue
With the problematic component identified, we examined its implementation. Looking at the CSS, we discovered the animation was using the top
property:
@keyframes move1 {
50% {
top: 70px;
}
100% {
top: -300px;
background: radial-gradient(circle, #f1b9ff 0%, transparent 60%);
}
}
While this wasn’t causing actual layout shifts, it revealed a more fundamental performance issue. Animating the top
property forces the browser to recalculate the layout on every frame of the animation, triggering expensive “reflow” operations.
These calculations happen on the CPU’s main thread, which is also responsible for handling user interactions and JavaScript execution. The result was potentially reduced responsiveness during the animation and inefficient resource usage.
Implementing the solution
The fix addressed both the CLS false positive and the underlying performance issue. Instead of animating the top
property, we switched to using transform: translateY()
:
@keyframes move1 {
50% {
transform: translateY(70px);
}
100% {
transform: translateY(-300px);
background: radial-gradient(circle, #f1b9ff 0%, transparent 60%);
}
}
This change was powerful for several reasons:
- GPU acceleration: The
transform
property is handled by the GPU during the compositing phase of rendering, bypassing expensive layout recalculations. - CLS improvement: Transform-based animations don’t trigger the layout shift detection algorithms, resolving the false positive.
- Performance gains: By offloading the animation to the GPU, we freed up the main thread to handle other tasks, improving overall responsiveness.
Lessons learned and best practices
This experience reinforced several important principles for our team:
Always animate transform and opacity: These properties bypass layout recalculation and are handled by the GPU, providing better performance regardless of whether CLS is affected.
Avoid animating layout properties: Properties like
top
,left
,width
,height
, andmargin
should generally not be animated due to their performance impact.Focus on performance over metrics: While fixing the CLS score was beneficial, the real win was the performance improvement from GPU acceleration.
Test on real devices: Performance differences between CPU and GPU animations are more apparent on lower-powered devices. Don’t hesitate to throttle CPU and network in the Chrome Dev Console.
Monitor Core Web Vitals continuously: We now have automated monitoring in place to catch both real issues and false positives early.
This relatively simple change had a significant impact on our site’s performance. Even though the original CLS issue was likely a false positive, it led us to discover and fix a genuine performance problem that was affecting user experience.
By sharing this experience across our development team, we’ve established better practices for animations throughout our codebase, ensuring we maintain high performance standards as our marketing site continues to evolve.
Conclusion
Our experience at Spendesk highlights how Core Web Vitals investigations can uncover real performance issues, even when the initial metric might be misleading. While the CLS warning for our banner animation appeared to be a false positive—since no actual layout shifts were occurring—it led us to discover a significant performance optimization opportunity.
This case study demonstrates key principles for web developers:
- Prioritize performance over metrics: GPU-accelerated animations with
transform
andopacity
provide better user experience regardless of their impact on specific scores - Use diagnostic tools as starting points: Metrics like CLS can point you toward areas that need investigation, even if the underlying issue differs from what the metric suggests
- Understand the browser’s rendering pipeline: Knowing how layout, paint, and compositing work helps you make informed decisions about animation implementation
By consistently applying these principles, we’ve not only improved our marketing website’s performance metrics but also created smoother, more responsive animations that enhance the user experience. This approach to animation optimization has become standard practice across our development team, ensuring we maintain high performance standards as our digital presence evolves.