transform 和 opacity 仅触发合成,性能安全;width、height、left、top、color 等触发 Layout 或 Paint,开销高;transition 应明确指定属性而非 all;will-change 需谨慎使用并及时清除;优先用 transform 替代位移/缩放类布局属性。

哪些 CSS 属性触发布局(Layout)或绘制(Paint)?
过渡动画是否卡顿,关键看它动的是哪类属性。浏览器渲染流水线中,transform 和 opacity 只触发合成(Composite),走 GPU 加速,几乎不掉帧;而 width、height、left、top、color、background-color 等会强制触发 Layout 或 Paint,尤其在高频动画中极易造成 60fps 崩溃。
-
transform(含translate、scale、rotate)→ 合成层,安全 -
opacity→ 合成层,安全 -
width/height→ 触发 Layout + Paint,高开销 -
margin/padding→ 触发 Layout,慎用 -
box-shadow→ 触发 Paint,复杂阴影会明显拖慢
transition 应该只写具体属性,别用 all
用 transition: all 0.3s 看似省事,实则埋雷:只要元素任意可动画属性变化(比如 JS 改了 color,或伪类加了 border),整个过渡逻辑就会被拉起,可能意外触发昂贵的重排。更糟的是,浏览器无法对 all 做优化预判。
- ✅ 推荐:
transition: transform 0.3s ease, opacity 0.3s ease - ❌ 避免:
transition: all 0.3s - ⚠️ 注意:
transition-property: background-color虽然明确,但仍是 Paint 级别,不如用transform模拟视觉位移
用 will-change 提前声明动画意图
will-change 不是“开启性能开关”,而是向浏览器发出信号:“这个元素接下来很可能动”,让其提前升格为独立合成层(layer)。但它有内存和管理成本,不能滥用。
- 仅对即将动画的元素临时设置:
will-change: transform - 动画结束后应主动清除(例如用 JS 切换 class 或监听
transitionend) - ❌ 不要全局写
* { will-change: transform }—— 会创建大量无效图层,反而拖慢滚动和内存 - Chrome DevTools 的 “Layers” 面板可验证是否成功分层
实际替换方案:用 transform 模拟常见位移动画
很多场景本想改 left/top 或 margin,其实完全可用 transform: translate() 替代,视觉效果一致,性能天差地别。
立即学习“前端免费学习笔记(深入)”;
.box {
/* ❌ 低效 */
transition: left 0.3s;
left: 0;
}
.box.active {
left: 100px;
}
/ ✅ 高效等价写法 /
.box {
transition: transform 0.3s;
transform: translateX(0);
}
.box.active {
transform: translateX(100px);
}
同理:width → 用 transform: scale() 模拟缩放;opacity 本身已是合成级,可放心用;需要“隐藏”时优先用 visibility: hidden 或 opacity: 0,而非 display: none(后者会彻底销毁渲染树)。
真正影响性能的从来不是 transition 这个声明本身,而是它背后驱动的属性类型和浏览器不得不做的工作。选错属性,再短的持续时间也卡;选对了,200ms 和 500ms 感知差异极小。











