1.9 KiB
1.9 KiB
| title | description | date | tags | image | |||
|---|---|---|---|---|---|---|---|
| CSS 动画性能优化:从掉帧到 60fps | 分享 CSS 动画性能优化的实战经验,理解浏览器渲染管线,写出丝滑的动画效果。 | 2026-05-20 |
|
动画为什么会卡
浏览器的渲染管线大致是:JavaScript → Style → Layout → Paint → Composite。
动画卡顿的根源在于触发了 Layout 或 Paint 阶段。每次滚动或动画帧只有约 16ms(60fps),如果 Layout 或 Paint 耗时过长就会掉帧。
只触发 Composite 的属性
只有 transform 和 opacity 不会触发 Layout 和 Paint,因为它们可以完全在合成器线程完成:
/* ✅ 推荐:只触发 Composite */
.element {
transform: translateX(100px);
opacity: 0.5;
}
/* ❌ 避免:触发 Layout */
.element {
left: 100px;
width: 200px;
}
使用 will-change 提示浏览器
.element {
will-change: transform;
}
告诉浏览器"这个元素即将发生变化",浏览器会提前将元素提升到独立的合成层。但不要滥用,每个合成层都会消耗 GPU 内存。
使用 FLIP 技术
对于无法用 transform 替代的动画(如改变元素位置),使用 FLIP 模式:
- First:记录元素初始位置
- Last:记录元素最终位置
- Invert:计算差值并反向应用
- Play:移除反向变换,添加过渡动画
const first = el.getBoundingClientRect()
// 修改布局...
const last = el.getBoundingClientRect()
const invert = first.top - last.top
el.style.transform = `translateY(${invert}px)`
requestAnimationFrame(() => {
el.style.transition = 'transform 0.3s'
el.style.transform = ''
})
小结
动画性能优化的核心就一条:尽量让动画只触发 Composite。用 transform 代替 top/left,用 opacity 代替 visibility,必要时用 will-change 和 FLIP 技术。