Why Only Transform and Opacity Are GPU-Accelerated in CSS Animations: Complete Performance Guide
Only transform and opacity are GPU-accelerated because they skip the browser's layout and paint stages entirely, running purely during the compositing phase.
CSS animations can achieve smooth 60fps performance only when the browser offloads work to the GPU. The emilkowalski/skills repository codifies this as a strict performance rule: only animate transform and opacity to avoid jank and maintain responsive UIs.
How the Browser Rendering Pipeline Works
Modern browsers render web pages through three sequential stages. Understanding this pipeline explains why most properties kill performance when animated.
The Three Stages
- Layout – Calculates element positions, dimensions, and document flow
- Paint – Fills pixels for visual properties like colors and borders
- Composite – GPU combines layers into the final screen image
GPU acceleration occurs only when an animation confines itself to the composite stage. Any property touching layout or paint forces the CPU to recalculate and rasterize on every frame.
Why Transform and Opacity Stay on the GPU
According to skills/review-animations/STANDARDS.md at line 112, these two properties are explicitly designated as composited-only.
Transform
The transform property applies matrix operations to existing layers:
/* GPU-accelerated movement, scaling, rotation */
.element {
transform: translate3d(0, 20px, 0) scale(1.1) rotate(5deg);
}
The GPU receives pre-built layers and applies coordinate transformations mathematically. No geometry recalculation occurs. The element's size and position in document flow remain unchanged.
Opacity
The opacity property blends layer alpha values during compositing:
/* GPU-accelerated fade effect */
.element {
opacity: 0.5;
}
The GPU simply adjusts a blending coefficient. The painted pixels underneath need no recomputation.
Properties That Force Layout (Reflow)
Animating these properties triggers complete geometry recalculation, cascading through parent and sibling elements:
width/heightmargin/paddingtop/right/bottom/leftborder-width
The skills/review-animations/SKILL.md file at line 35 flags these as findings requiring remediation. Line 71 specifically urges developers to "move it to the GPU" by replacing dimension animations with transform equivalents.
Properties That Force Paint
These properties require pixel repainting without layout changes, still CPU-bound:
background-colorborder-colorbox-shadowoutline
The Transition: All Trap
The repository explicitly warns against transition: all in SKILL.md at line 86. This shorthand unintentionally captures off-GPU properties when developers add new styles later.
/* ❌ Dangerous: catches future non-GPU properties */
.element {
transition: all 200ms ease;
}
/* ✅ Explicit: only what you intend to animate */
.element {
transition: transform 200ms ease,
opacity 200ms ease;
}
Practical Refactoring Examples
Height Animation to Scale Transform
/* ❌ Bad: animates height, forces layout */
.accordion {
height: 0;
transition: height 200ms ease-out;
}
.accordion.open {
height: 200px;
}
/* ✅ Good: uses scaleY, stays on GPU */
.accordion {
transform: scaleY(0);
transform-origin: top;
transition: transform 200ms ease-out;
}
.accordion.open {
transform: scaleY(1);
}
Slide Animation with Translate
/* ❌ Bad: animates left, forces layout */
.slide {
position: relative;
left: -100%;
transition: left 300ms ease;
}
.slide.visible {
left: 0;
}
/* ✅ Good: uses translateX, stays on GPU */
.slide {
transform: translateX(-100%);
transition: transform 300ms ease;
}
.slide.visible {
transform: translateX(0);
}
Fade Animation with Opacity
/* ✅ Correct: opacity is GPU-accelerated */
.toast {
opacity: 0;
transform: translateY(8px);
transition:
opacity 200ms ease-out,
transform 200ms ease-out;
}
.toast.visible {
opacity: 1;
transform: translateY(0);
}
Framework-Specific Warnings
As noted in SKILL.md at line 35, abstracted transforms can still cause problems. Framer Motion's x, y, and scale props compile to CSS transforms but may fallback to non-GPU-friendly implementations under memory pressure. Always verify the actual computed styles in DevTools.
Performance Targets from the Repository
The skills/emil-design-eng/SKILL.md file at line 509 establishes these thresholds for maintainable animations:
- Maximum duration: 300ms for UI feedback
- Target frame rate: 60fps consistently
- Trigger condition: 17ms frame budget during heavy main-thread load
GPU-accelerated transform and opacity meet these targets because they execute independently of JavaScript execution, DOM mutations, and other main-thread work.
Summary
transformandopacityare the only CSS properties that skip layout and paint entirely- Layout properties (
width,height,margin,left, etc.) force expensive geometry recalculation - Paint properties (
background-color,border-color) require CPU pixel rasterization transition: allis an anti-pattern that accidentally animates non-GPU properties- Refactor dimension animations to use
scaleandtranslateinsidetransform - Keep animations under 300ms and verify 60fps in Chrome DevTools Performance panel
Frequently Asked Questions
Can any other CSS properties be GPU-accelerated?
No. According to STANDARDS.md in the emilkowalski/skills repository, only transform and opacity are classified as composited-only properties. Some browsers experiment with filter acceleration, but cross-browser consistency makes transform and opacity the only reliable choices for production applications.
Why does animating left feel slower than translateX?
left triggers layout recalculation for the affected element and potentially its siblings and ancestors. translateX operates on an existing compositor layer without touching the layout tree. The visual result appears identical, but translateX executes entirely on the GPU while left consumes main-thread CPU cycles.
How do I verify my animation runs on the GPU?
Open Chrome DevTools, enable Paint flashing in the Rendering panel, and trigger your animation. Green rectangles indicate repaints (CPU work). GPU-accelerated animations show no paint flashing. Additionally, the Performance panel's frame view shows no purple "Layout" or green "Paint" blocks during transform/opacity animations.
Is will-change necessary for GPU acceleration?
Not for transform and opacity in most cases. Modern browsers automatically promote elements with these properties to their own compositor layers. Explicit will-change: transform can help in complex layer management scenarios but should be removed after animation completes to prevent excessive memory consumption from unused layers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →