核心是只用transform和opacity,二者走gpu合成层、不触发重排重绘;避开width、height、top、left等布局属性,必要时用translate替代位移、scaley+overflow隐藏替代height动画,并通过layers面板验证图层提升。

动画中避开重排,核心就一条:别碰任何影响布局的属性。浏览器一检测到这些值变了,就得从头算位置、尺寸、行高、流式关系——这步叫重排(reflow),开销大、卡顿明显,尤其在移动端。
只用真正安全的两个属性
transform 和 opacity 是唯二被浏览器深度优化的动画属性。它们不参与布局计算,也不触发全量重绘,而是走 GPU 合成层(compositing layer)。
-
transform 包括 translateX/Y/Z、scale、rotate、skew,但注意要合并写法,比如用
transform: translate(10px, 5px),别拆成两行分别设translateX和translateY,后者会覆盖且可能引发额外样式计算 -
opacity 必须是合法小数,如
opacity: 0.7;opacity: 70%是无效写法,会被忽略 - 避免混搭:比如同时设
left: 20px和transform: translateX(20px),left依然会触发重排
绕开危险属性的替代方案
width、height、top、left、right、bottom、margin、padding、font-size、border 等,改一个就重排一次。高频动画里绝对禁用。
- 位移不用
top/left→ 改用transform: translateY()或translateX() - 展开收起不用
height→ 改用transform: scaleY()+overflow: hidden,或预设足够大的max-height - 显示隐藏不用
display: none切换 → 用opacity: 0+visibility: hidden(后者保证不占布局空间) - 移动端慎用小数位移,如
translateX(0.001px)可能被 Safari 忽略,建议 ≥ 0.01px 或直接用整数
让元素真正“隔离”出来
光用 transform 不够——元素还在文档流里,父容器仍要为它预留空间、参与行高计算,兄弟节点可能被推挤抖动。
- 加
transform: translateZ(0)或will-change: transform提升为独立合成层;移动端优先选前者,Safari 对will-change支持弱且易误触发 - 多个相邻动画元素,统一包进一个容器,只对该容器提升图层,别每个子项都加
- 给动画容器加上
contain: paint或overflow: hidden,明确划定绘制边界,防止溢出影响外部 - 初始状态必须显式声明 transform,比如
transform: translateY(0),否则第一帧可能跳变
检查与验证不能少
优化不是写了就生效,得验证是否真进了合成层。
- Chrome DevTools → Layers 面板,拖动动画看是否有独立图层生成
- Performance 面板录制动画过程,观察 layout 和 paint 的耗时占比,理想情况 layout 应几乎为零
- 避免滥用
will-change:它只是“预告”,不是“开关”,加太多反而增加内存负担和图层管理开销











