--- title: "Main-Thread Free Animations" category: studio-standards status: required url: https://webspecification.com/spec/studio-standards/main-thread-free-animations/ source_repo: undefined licence: CC-BY-4.0 --- # 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. ```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.