Frame-based scroll animation can hurt LCP and CLS — unless you do it right. Here's how to add scroll animation without trashing Core Web Vitals.
Where Scroll Animation Hurts Performance
Three failure modes:
- LCP (Largest Contentful Paint) — if your scroll animation is the hero and frames load slowly, LCP balloons
- CLS (Cumulative Layout Shift) — if the animation container has no explicit height, it shifts the page when frames load
- Total Blocking Time — naive scroll listeners fire dozens of times per scroll event, blocking the main thread
Fix #1: Lazy Load Beyond the First Frame
Load only the first frame eagerly. Lazy-load the rest as the user approaches the animation. This keeps LCP low while still delivering the full sequence.
Fix #2: Set Explicit Container Dimensions
Always set width and height on the canvas container. CLS = 0 when dimensions are reserved, no matter how slowly frames load.
Fix #3: Throttle the Scroll Listener with requestAnimationFrame
Naive scroll listeners can fire 60+ times per second. Wrap your frame-paint logic in requestAnimationFrame so you paint once per browser frame, not once per scroll event.
Fix #4: Use Modern Image Formats
Serve frames as WebP or AVIF, not JPEG. AVIF reduces frame size by ~50% with the same visual quality. CDN delivery + AVIF + lazy loading = scroll animation that doesn't hurt your Lighthouse score.
Fix #5: Reduce Frame Count on Mobile
Mobile devices have less bandwidth and CPU. Serve a 60-frame sequence on mobile vs. 120 on desktop. The visual difference is minor; the performance gain is significant.
How ScrollerSites Handles This
ScrollerSites does all five fixes automatically — lazy-loaded frames, explicit container dimensions, rAF-throttled scroll listener, AVIF/WebP delivery, and separate mobile frame sets. The embed snippet you paste into your site is performance-tuned out of the box.
If you build it yourself, plan for these performance considerations from day one. They're much harder to retrofit than to design in.