仅用 transform 和 opacity 做动画可跳过 layout 和 paint,由 gpu 直接合成;避免 left/top、width/height、margin 等触发布局的属性,禁用 transition: all,显式声明过渡属性,并确保父容器隔离渲染边界及元素有初始 transform 值。

只用 transform 和 opacity 做动画
浏览器对这两个属性做了合成层(compositor)专属优化:它们不改变文档流、不修改盒模型尺寸,因此动画帧可跳过 Layout 和 Paint 阶段,直接由 GPU 合成。其他任何属性——哪怕只是 color 或 background-color——都属于 Paint 阶段,高频变化时容易掉帧。
常见错误包括:left/top 位移、width/height 缩放、margin 推挤。这些都会强制每帧重跑 Layout 流水线,尤其在滚动中叠加动画时,卡顿肉眼可见。
-
transform: translateX(100px)✅ 安全;left: 100px❌ 触发重排 -
opacity: 0.7✅ 安全;opacity: 70%❌ 静默失效(必须是小数) -
transform: scale(1.2) rotate(5deg)✅ 多函数组合仍走合成层
禁用 transition: all 和隐式简写
写 transition: 0.3s 等价于 transition: all 0.3s,等于把所有可动画属性都拉进队列。哪怕 hover 时只改了 z-index 或 cursor,也可能意外触发冗余过渡,造成状态错乱或卡顿。
正确做法是显式声明关键属性:
- ✅
transition: transform 0.3s ease, opacity 0.3s ease - ❌
transition: margin 0.3s(margin是简写,内部拆成四个方向,任一变化都可能触发布局) - ❌
transition: all 0.3s(过度宽泛,调试困难,性能不可控)
避免 JS 中混搭布局修改与合成动画
动态加样式时,顺序和组合很关键。比如先设 el.style.transform = 'translateX(0)',再补一句 el.style.width = '200px',后者立刻破坏 GPU 加速路径,整条动画退化为 CPU 渲染。
同样危险的操作:
- 在
@keyframes里同时写transform: translateX(100px)和height: 200px - 用
getBoundingClientRect()或offsetTop强制同步读取布局——这会引发 layout thrashing - 给动画元素的父容器加
filter或非 identity 的transform(如rotate(0.1deg)),会压制子元素的合成层提升
隔离渲染边界并预设初始值
就算子元素只用 transform,如果父容器没做隔离,动画溢出仍可能推挤兄弟节点,产生“呼吸感”抖动。最简单有效的办法是加 overflow: hidden。
另一个常被忽略的点:初始 transform 值必须显式写出。比如动画从 translateY(-20px) 到 translateY(0),但若元素原本没设 transform: translateY(-20px),第一帧就会跳变。
- ✅ 父容器加
overflow: hidden或contain: layout paint - ✅ 动画前确保元素有明确初始态:
transform: translateY(-20px),不是空着靠动画“从无到有” - ⚠️
will-change: transform不是开关,仅作提示;滥用会增加内存开销和图层管理成本,建议只在动画触发前临时设置,结束后立即设回auto
transform 声明——这两处不处理,哪怕代码全用 transform,第一帧也大概率跳、滚动中也容易抖。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











