减少重排的核心是批量变更、离线操作与读写分离:用documentfragment批量插入节点,css类代替内联样式,transform/opacity替代几何属性动画,并先读取后写入布局信息。

减少重排(Reflow)的核心是避免让浏览器反复重新计算元素的几何信息。每次重排都要走完整的布局流水线,开销大、延迟高,尤其在循环操作或高频交互中极易卡顿。关键不在于“少改 DOM”,而在于“改得聪明”——把多次变更压缩成一次布局计算。
用 DocumentFragment 批量插入节点
逐个 appendChild 100 次,大概率触发 100 次重排;换成 DocumentFragment,只在最后插入时算一次。
- 调用
document.createDocumentFragment()创建离线容器 - 所有新节点都加进这个 fragment,不挂载、不渲染、零重排
- 最后执行一次
parent.appendChild(fragment),浏览器统一计算整棵子树布局
实测首屏时间可从 800ms 降到 150ms 左右。注意:fragment 插入后自动清空,不可复用,多批操作需新建。
样式修改尽量批量或走 CSS 类
直接操作 element.style.xxx 属性,尤其是 width/height/top/left 等几何属性,每次赋值都可能触发重排;而切换 class 或设置 cssText 是一次性声明,浏览器可合并处理。
- 避免
el.style.width = '200px'; el.style.height = '100px';这类连续写入 - 改用
el.className = 'card--large';或el.setAttribute('class', '...') - 必须动态设样式时,优先用 CSS 自定义属性:
el.style.setProperty('--size', '200px'),再在 CSS 中用width: var(--size)—— 浏览器内部优化,不强制重排
动画优先用 transform 和 opacity
位移、缩放、旋转、透明度变化这类操作,浏览器会交给合成层(composite layer)处理,跳过布局和绘制阶段,只涉及重绘甚至不重绘(靠 GPU 合成)。
- 用
transform: translateX(100px)替代left: 100px - 用
opacity: 0.5替代visibility: hidden或频繁改display - 避免在动画中读取
offsetWidth、getComputedStyle等会强制同步布局的 API
读写分离 + 缓存尺寸信息
先批量读取所有需要的布局数据(如 offsetTop、clientHeight),再集中写入变更。否则“读→写→读→写”会形成多次强制重排。
- ❌ 错误模式:
for (let i = 0; i - ✅ 正确做法:先遍历一次收集所有
offsetHeight,存进数组;再遍历一次统一设置样式 - 对固定区域元素,可缓存其尺寸,在 resize 等事件外不再重复读取











