width、height、margin、padding、border、top、left、right、bottom、font-size、line-height、display、visibility等属性一动即触发重排,因它们改变元素几何尺寸或文档流位置,强制浏览器重新计算布局树。

直接用 width、padding、top 或 left 做动画,浏览器必须每帧重跑整个布局流水线——这不是卡顿,是主动邀请重排上门。
哪些CSS属性一动就触发重排?
所有影响盒模型几何尺寸或文档流位置的属性,都会强制浏览器重新计算布局树。这不是“可能慢”,而是“必然重排”:
-
width、height、margin、padding、border:改一个像素,后代、兄弟、父容器甚至后续流内元素都要重算位置和换行 -
top、left、right、bottom:即使元素已position: absolute,只要还在动画规则里写它们,就仍走 layout 阶段 -
font-size、line-height、text-align:文本流变化会连锁影响块级容器高度与折行 -
display(如block↔inline)、visibility(visible↔hidden):前者删布局,后者跳绘制,但都非合成层属性
为什么只用 transform 和 opacity 能避开重排?
这两个属性被浏览器标记为“仅合成层可处理”,意味着它们绕过 style → layout → paint 全流程,由 GPU 独立完成插值与渲染:
-
transform(包括translateX、scaleY、rotateZ)只改变图层在合成器中的最终呈现矩阵,不参与任何布局计算 -
opacity只控制图层透明度混合,连重绘都不触发;但注意:background-color一混进来,整条动画就降级回 CPU 渲染 - 前提:元素需成为独立合成图层——可通过
transform: translateZ(0)或will-change: transform触发,但后者慎用(见下条)
will-change 不是加速开关,而是内存预分配指令
它不会让 width 动画变快,只会让浏览器提前分配显存、创建纹理。滥用等于主动吃内存:
立即学习“前端免费学习笔记(深入)”;
-
will-change: width是非法值,所有浏览器都会忽略;will-change: transform才有效 - 全局加
will-change: transform在低端安卓机上易触发 OOM,页面白屏或卡死 - 正确做法:动画开始前 1–2 帧动态设置
el.style.willChange = 'transform',结束后立刻设回'auto' - 验证是否生效:Chrome DevTools → Layers 面板——没看到独立图层,说明提升失败(常见于父容器有
filter或非 identitytransform)
最容易被忽略的“隐性重排”陷阱
哪怕你已经用 transform 写好了动画,一行 JS 就能让它全毁:
- 在动画帧中读取
offsetWidth、getBoundingClientRect()、scrollTop等布局相关属性,会强制触发同步 layout,哪怕只读一次 - 混用
left和transform:虽然transform会覆盖left的视觉效果,但样式引擎仍可能多做一次 layout 计算 - 父容器未设
position: relative却给子元素加position: absolute:定位基准错乱,导致元素飞走,同时父容器高度塌陷,引发连锁重排
真正卡住人的,从来不是某个属性本身,而是把“能动”和“该动”搞混了——width 能被 transition,不等于它该被 transition。


















