Main-Thread Free Animations
Enforcing that all scroll-driven micro-interactions use CSS-native algorithms.
What is it?
The strict requirement that UI animations, particularly those tied to user scrolling, must be executed entirely on the browser’s compositor thread using CSS, rather than calculated on the JavaScript main thread.
Why does it matter?
Binding window.addEventListener("scroll", ...) forces the browser’s main thread to constantly evaluate layout math while the user is actively scrolling. This competes with other scripts, causing dropped frames and “jank”. CSS-native animations are offloaded to the GPU, guaranteeing silky-smooth 60fps (or 120fps) performance regardless of how busy the main thread is.
How to implement it
1. CSS Scroll-Driven Animations
Use the modern animation-timeline property to bind an animation directly to the scroll progression of the viewport, entirely in CSS.
.progress-bar {
scale: 0 1;
transform-origin: left;
animation: grow-progress linear;
animation-timeline: scroll(root block);
}
@keyframes grow-progress {
to { scale: 1 1; }
}
2. Intersection Observers for Triggers
If you simply need an element to fade in when it enters the viewport, use IntersectionObserver to toggle a CSS class, rather than listening to scroll events.
Verification
- Open Chrome DevTools -> Rendering. Enable “Paint flashing” and “Layout Shift Regions”. Scroll the page. If your animations cause massive green rectangles (repaints) or if the main thread is spiking in the Performance tab, you are doing it wrong.