top/left 触发 layout 因其改变几何布局,需重排→重绘→合成;transform/opacity 仅影响合成层,元素提升为独立图层后只触发 composite,保障 60fps。

为什么 top/left 触发 layout,而 transform/opacity 不会
浏览器渲染流水线中,top、left 等几何属性变更会强制触发 layout(重排)→ paint(重绘)→ composite(合成) 全流程;而 transform 和 opacity 属于「仅影响合成层」的属性,只要元素已提升为独立图层(例如通过 will-change: transform 或 transform: translateZ(0)),就只走 composite 阶段——这是 60fps 动画的关键。
transition 应该写在哪个元素上?写在哪几个属性上?
必须把 transition 写在「将要动画的元素本身」上,且只声明真正会变化的属性,避免冗余监听:
-
transition: transform 0.3s ease, opacity 0.3s ease;✅ 精确控制 -
transition: all 0.3s;❌ 触发不必要的属性监听,可能意外激活width、height等高成本属性 - 不要写在父容器上期望“继承”过渡效果——
transition不继承
如何确保 transform 动画不闪屏、不模糊?
常见问题:用 transform: translateX(10px) 后文字变细、边缘发虚。这是因为像素未对齐(subpixel rendering)。解决方式:
- 强制开启硬件加速图层:
transform: translateZ(0);或will-change: transform; - 对齐到整数像素:用
transform: translateX(10px);而不是transform: translateX(10.5px); - 避免和
scale()混用(除非你明确需要缩放),因为非 1 的 scale 会放大亚像素问题 - 移动端注意:iOS Safari 对
will-change处理较激进,建议只在 hover/active 状态动态添加,而非常驻
opacity 过渡卡顿?检查是否被其他属性拖累
opacity 本应是高性能属性,但实践中卡顿往往来自干扰项:
立即学习“前端免费学习笔记(深入)”;
- 父元素有
filter: blur(2px);—— blur 会禁用合成优化,整个元素退回到 paint 阶段 - 元素内含大量未优化的 SVG 或 canvas —— opacity 变化虽快,但每次 composite 仍需重新合成复杂内容
- 同时动画多个兄弟元素且未分层 —— 建议给每个动效元素加
transform: translateZ(0);,让它们各自成为独立合成层 - 使用
opacity: 0;隐藏时,记得配合pointer-events: none;和visibility: hidden;(如果不需要响应交互),否则透明元素仍参与事件捕获和布局计算
真正影响性能的从来不是 transition 本身,而是你让什么属性去动、它动的时候带上了哪些隐式开销。哪怕只改一行 CSS,也要问一句:这一帧,浏览器到底重排了没?











