CSS Performance: Why Your Animations Are Janky and How to Fix Them
Smooth 60fps animations require understanding the browser rendering pipeline. Learn which CSS properties are safe to animate and which ones destroy performance.
You added a slide-in animation to your sidebar. It works, but it stutters. The menu expand feels like it's running at 15fps. Your loading spinner — a simple rotation — somehow makes the entire page feel sluggish on mobile.
The problem isn't CSS animations themselves. It's which properties you're animating and how the browser renders them.
The Browser Rendering Pipeline
Every frame the browser paints goes through five steps: JavaScript → Style → Layout → Paint → Composite. The key to smooth animations is staying as far right in this pipeline as possible.
- Layout properties (width, height, top, left, margin, padding): Changing these triggers layout recalculation for the entire document — the most expensive operation.
- Paint properties (background-color, box-shadow, border-radius): Triggers repaint but not layout. Still expensive for large areas.
- Composite properties (transform, opacity): Only triggers compositing — handled entirely by the GPU. This is where 60fps lives.
The Two Safe Properties
For smooth animations, you should animate only transform and opacity. Everything else is a compromise. Here's how to replace common janky patterns:
/* ❌ JANKY: Animating width triggers layout on every frame */
.sidebar {
width: 0;
transition: width 0.3s ease;
}
.sidebar.open {
width: 280px;
}
/* ✅ SMOOTH: Transform is GPU-composited */
.sidebar {
transform: translateX(-100%);
transition: transform 0.3s ease;
width: 280px; /* Fixed width, no layout change */
}
.sidebar.open {
transform: translateX(0);
}
/* ❌ JANKY: Animating top/left */
.tooltip {
top: 0;
transition: top 0.2s ease;
}
.tooltip.visible {
top: -40px;
}
/* ✅ SMOOTH: Use translateY instead */
.tooltip {
transform: translateY(0);
transition: transform 0.2s ease;
}
.tooltip.visible {
transform: translateY(-40px);
}
will-change: Use Sparingly
The will-change property hints to the browser that an element will animate, promoting it to its own compositor layer. But it's not free — each layer consumes GPU memory.
/* ✅ Apply before animation starts, remove after */
.card:hover {
will-change: transform;
}
.card.animating {
transform: scale(1.05);
transition: transform 0.2s ease;
}
/* ❌ Don't apply will-change to everything */
* {
will-change: transform, opacity; /* GPU memory explosion */
}
Use will-change on elements that will definitely animate soon (e.g., on hover before the transition starts). Remove it after the animation completes. Never apply it globally.
contain: The Underused Performance Property
The contain property tells the browser that an element's internals won't affect the rest of the page. This lets the browser skip layout and paint recalculations for contained elements:
/* Each card is an isolated layout boundary */
.card {
contain: layout style paint;
}
/* For off-screen or hidden content */
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
content-visibility: auto is particularly powerful — it skips rendering for off-screen elements entirely, then renders them as they scroll into view.
Diagnosing Jank with DevTools
Chrome DevTools' Performance panel shows exactly what's happening per frame:
- Open Performance tab, click Record
- Trigger your animation
- Stop recording and zoom into the animation frames
- Look for long "Layout" or "Paint" blocks (purple and green bars)
- Frames exceeding 16.6ms (the 60fps budget) will show a red triangle
Enable "Rendering → Paint flashing" to see which areas repaint during animations. Green flashes on large areas indicate expensive repaints.
Takeaways
- Only animate
transformandopacityfor guaranteed smooth performance - Replace width/height/top/left animations with transform equivalents
- Use
will-changesparingly and temporarily — it costs GPU memory - Apply
containandcontent-visibilityto isolate expensive sections - Use DevTools Performance panel to identify layout thrashing in animations
Admin
Cal.com
Open source scheduling — tự host booking system, thay thế Calendly. Free & privacy-first.
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!