The Web Animation Performance Tier List
Why transform is S-Tier and width is F-Tier—mastering the browser rendering pipeline
Not all CSS properties are created equal. When you animate them, the browser has to do vastly different amounts of work. Understanding the browser's rendering pipeline—Layout, Paint, and Composite—is the key to silky smooth 60fps animations.
The Render Pipeline
To put pixels on the screen, the browser goes through three main stages:
- Layout: Calculating geometry (width, height, position). This is expensive and affects surrounding elements.
- Paint: Filling in pixels (colors, shadows, borders). This is moderately expensive.
- Composite: Layering the painted parts together. This is cheap and happens on the GPU.
The Tier List
S-Tier: The Compositor Thread
These properties can be handled entirely by the GPU compositor thread. They don't trigger Layout or Paint, meaning they remain smooth even if the main JavaScript thread is blocked.
transform(translate, scale, rotate)opacityfilter(sometimes)clip-path(sometimes)
A-Tier: Layered Main Thread
Animations driven by JavaScript (like requestAnimationFrame) that only touch S-Tier properties. They are fast but run on the main thread, so they can stutter if your JS is heavy.
C-Tier: Paint Triggers
Properties that don't change geometry but require repainting the element. The browser has to do work, but it doesn't have to recalculate the entire page layout.
colorbackground-colorbox-shadow
D-Tier: Layout Triggers (Avoid!)
Properties that change geometry. Animating these forces the browser to recalculate the layout of the element and its children and siblings every single frame. This is the #1 cause of jank.
width/heighttop/left/right/bottommargin/padding
F-Tier: Layout Thrashing
The absolute worst case: reading a layout property (like offsetWidth) immediately after writing one, inside a loop. This forces the browser to perform a synchronous layout calculation multiple times per frame.
The Takeaway
Always reach for S-Tier properties first. Need to move an element? Use transform: translate() instead of top/left. Need to resize it? Use transform: scale() instead of width/height whenever possible. Your users' batteries (and frame rates) will thank you.
Advertisement
Explore these curated resources to deepen your understanding
Official Documentation
Related Insights
Explore related edge cases and patterns
Advertisement