CSS 动画性能
流畅动画的核心是减少重排重绘,充分利用 GPU 合成层。
渲染管线
浏览器渲染分为三阶段:
CSS
样式计算 → 布局(重排) → 绘制(重绘) → 合成
动画性能层级:
- 最高:仅合成层变化(transform、opacity)
- 中等:仅重绘
- 最差:触发重排
高性能动画属性
transform
CSS
/* 好:仅触发合成层 */
.box {
transition: transform 0.3s ease;
}
.box:hover {
transform: translateX(100px) scale(1.1);
}
/* 差:触发重排 */
.box:hover {
left: 100px;
width: 110%;
}
opacity
CSS
/* 好:仅触发合成层 */
.fade {
transition: opacity 0.3s ease;
}
.fade:hover {
opacity: 0.5;
}
属性性能对比
| 属性 | 是否触发重排 | 是否触发重绘 | 是否触发合成 | 推荐程度 |
|---|---|---|---|---|
| transform | ✗ | ✗ | ✓ | ★★★★★ |
| opacity | ✗ | ✗ | ✓ | ★★★★★ |
| color | ✗ | ✓ | ✗ | ★★★☆☆ |
| background | ✗ | ✓ | ✗ | ★★★☆☆ |
| width/height | ✓ | ✓ | ✗ | ★☆☆☆☆ |
| top/left | ✓ | ✓ | ✗ | ★☆☆☆☆ |
| margin/padding | ✓ | ✓ | ✗ | ★☆☆☆☆ |
强制 GPU 加速
JavaScript
.gpu-accelerated {
/* 触发合成层 */
transform: translateZ(0);
/* 或 */
will-change: transform;
}
过度使用
will-change会消耗大量内存,谨慎使用。
动画优化实践
使用 requestAnimationFrame
JavaScript
// 差:定时器不与屏幕刷新同步
setInterval(() => {
element.style.left = x + 'px';
}, 16);
// 好:与浏览器刷新同步
function animate() {
element.style.transform = `translateX(${x}px)`;
requestAnimationFrame(animate);
}
避免动画期间读取布局属性
CSS
// 差:动画中读取会强制同步布局
function animate() {
const width = element.offsetWidth; // 强制布局
element.style.transform = `translateX(${width}px)`;
}
// 好:提前读取,动画中只写
const width = element.offsetWidth;
function animate() {
element.style.transform = `translateX(${width}px)`;
}
降低动画元素复杂度
text
/* 动画元素尽量简单 */
.animated-element {
/* 避免复杂阴影 */
box-shadow: none;
/* 避免复杂背景 */
background: #fff;
/* 减少子元素 */
}
性能检测
Chrome DevTools → Performance → 录制动画:
- 绿色:FPS 帧率
- 紫色:重排
- 黄色:重绘
目标:保持 60fps(每帧 16.67ms 以内)。
要点总结
- 优先使用 transform 和 opacity 做动画
- 避免 width、height、top、left 等触发重排的属性
- 合理使用 will-change 提示浏览器优化
- 动画期间避免读取布局属性
- 使用 Chrome DevTools 检测动画性能
📝 发现内容有误?点击此处直接编辑