触发重排的属性开销最高
别名: 重排动画 · transform 合成 · will-change · 布局颠簸
概念解释
每一帧动画都要走完引擎允许的最短管线。改 top、left、width、height、margin 会让文档重新算几何,后面的绘制和合成都得重来。改 transform、opacity 往往可以只在合成器(compositor)上更新已有图层。触发重排的属性开销最高,说的是这条管线被点到哪一层:布局 > 绘制 > 合成。它解释的是单帧工作量从哪来,不是掉帧之后看起来有多难受,也不是要不要整段关掉动画。
机制
渲染一帧大致是:样式 → 布局 → 绘制 → 合成。几何属性写入 used box,布局阶段必须重跑依赖链,所有被影响的节点重新打绘制指令,合成器再把层贴到屏幕。transform 和 opacity 在独立层上时,布局和绘制可以跳过,合成器只改层的矩阵或透明度。will-change 或 3D 变换会提前把元素提升为层,让这条捷径稳定可走;提升过多则显存和上传变贵,等于用空间换掉一次布局。
同一视觉结果,属性选择决定是“每帧整页重排”还是“每帧改一层”。位移动画用 left 从 0 到 100,等于每帧让后续兄弟重新认位置;用 translateX 则盒子的布局矩形不变,只有层在动。宽度动画几乎无法只靠合成完成,因为行盒和子树几何都在变。
边界
SVG 的某些呈现属性、Canvas 自绘、游戏引擎的场景图,不走文档 CSS 管线,这条属性分层对它们不成立。已经在跑布局的界面(拖拽改宽度、分栏)本来就在改几何,用 transform 假装宽在变会和命中测试、滚动高度脱节。打印、静态导出没有逐帧管线。极短的一次性过渡(几十毫秒、面积很小)即使走布局,也未必掉出用户可辨的帧,但不能据此把列表里每项滚动都做成布局动画。
怎么落地
- 位移动画和淡入默认只动画
transform与opacity;需要改宽高时,动画一个包裹层的变换,或在手势结束时一次性写入几何,而不是逐帧写width。 - 对确定走合成的元素短时间使用
will-change,动画结束去掉,避免整页每个卡片都提升为层。 - 在性能面板看火焰图:动画期间若每帧都出现 Layout,就换属性;只剩 Composite 才是这条要的状态。
- 验证:同一动效分别用
left和translate实现,在中端机上看帧时长和 Layout 次数。布局版应明显更贵;合成版在命中测试仍指向视觉位置(必要时同步一个不可见的几何更新)。