强制同步布局 和 布局抖动 是导致页面在滚动或动画时发生卡顿的主要原因。
当我们用 JS 修改 DOM 元素的样式时,浏览器并不会立刻重排重绘,而是把这些修改放入队列中,等到下一帧再批量执行布局计算。
如果在修改样式的同一循环里,去读取某个几何样式属性(如 offsetHeight、clientWidth),浏览器为了保证返回准确的数据,不得不立即暂停 JS 执行,强制提前清空修改队列,进行完整布局计算。这就是强制同步布局。
如果这个“写入-读取”动作发生在一个循环里,会在极短时间引发大量布局计算,导致 CPU 占用率飙升,这种现象就是布局抖动。
读取以下属性或调用以下方法会引发强制布局:
offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidth, scrollHeightoffsetTop, offsetLeft, scrollTop, scrollLeftgetBoundingClientRect(), getComputedStyle(), scrollIntoView()解决循环里布局抖动的核心做法是:先批量读取并缓存结果,再批量写入。
可以利用 requestAnimationFrame 将写操作推迟到下一帧执行,从而保证当前帧只有读操作。也可以借助现成的库如 FastDOM 来统一调度读写队列。
尽量通过 Flexbox 或 Grid 等现代 CSS 布局特性来实现自适应,避免使用 JS 动态计算并设置宽高。