CSS 的 重绘(Repaint) 和 重排(Reflow,也称回流) 是浏览器渲染页面时的两种关键性能优化机制,它们的区别在于触发条件和性能开销。理解它们有助于优化页面性能,减少不必要的渲染开销。
1.重排(Reflow)
定义
重排是指浏览器重新计算元素的位置和几何属性(如宽度、高度、边距、边框等),并重新构建渲染树(Render Tree)的过程。重排会导致浏览器重新布局页面,可能影响多个元素甚至整个页面。
触发条件
当以下情况发生时,会触发重排:
- DOM 结构变化:添加、删除、移动 DOM 节点(如 appendChild()、removeChild())。
- 元素几何属性变化:修改宽度(width)、高度(height)、边距(margin)、内边距(padding)、边框(border)、字体大小(font-size)等。
- 浏览器窗口大小变化:如调整窗口大小、滚动页面。
- 计算偏移量:通过 offsetTop、offsetLeft、getComputedStyle() 等获取元素几何信息时,浏览器可能强制触发重排以返回最新值。
- 激活伪类:如 :hover、:focus 等状态变化可能影响布局。
性能影响
- 开销大:重排会重新计算布局,可能涉及整个文档或部分子树的布局,导致性能下降。
- 阻塞渲染:重排会阻塞浏览器渲染,直到布局计算完成。
示例
/* 修改几何属性会触发重排 */
.box {
width: 200px; /* 修改宽度 */
height: 100px; /* 修改高度 */
margin: 10px; /* 修改外边距 */
}
// 动态修改 DOM 或样式会触发重排
element.style.width = '300px'; // 重排
element.appendChild(newNode); // 重排
2.重绘(Repaint)
定义
重绘是指浏览器重新绘制元素的外观(如颜色、背景、边框、阴影等),但不改变元素的几何布局。重绘发生在重排之后,或仅修改不影响布局的属性时。
触发条件
当以下情况发生时,会触发重绘:
- 修改非几何属性:如 color、background-color、visibility、outline、box-shadow、text-decoration 等。
- 重排后的必然结果:重排后,浏览器必须重新绘制受影响的元素。
性能影响
- 开销较小:重绘仅涉及像素级别的绘制,不涉及布局计算,因此性能开销比重排小。
- 仍可能阻塞渲染:大量重绘仍可能导致卡顿。
示例
/* 修改非几何属性会触发重绘 */
.box {
color: red; /* 修改文字颜色 */
background: blue; /* 修改背景色 */
visibility: hidden; /* 修改可见性 */
}
// 修改不影响布局的属性会触发重绘
element.style.color = 'green'; // 重绘
element.style.visibility = 'hidden'; // 重绘
3.重排 vs 重绘:关键区别
| 特性 | 重排(Reflow) | 重绘(Repaint) |
|---|---|---|
| 定义 | 重新计算元素几何布局 | 重新绘制元素外观(不改变布局) |
| 触发条件 | 修改几何属性、DOM 结构、窗口大小等 | 修改颜色、背景、边框等非几何属性 |
| 性能开销 | 高(可能涉及整个文档或子树) | 低(仅影响元素外观) |
| 是否阻塞渲染 | 是(布局计算完成前无法渲染) | 是(但开销较小) |
| 关系 | 重新计算元素几何布局 | 重绘不一定需要重排 |
4.如何优化?
减少重排和重绘的技巧
- 批量修改样式
- 使用 classList.add()/remove() 替代直接修改 style。
- 通过 CSSText 或 class 批量修改样式:
// ❌ 多次触发重排 element.style.width = '100px'; element.style.height = '200px'; // ✅ 批量修改(减少重排) element.style.cssText = 'width: 100px; height: 200px;'; // 或使用 class element.className = 'new-class'; - 使用 visibility: hidden , display: none
- 需保留空间 → visibility: hidden + opacity: 0(仅重绘)。
- 需释放空间 → display: none(触发重排,但避免无效渲染)。
- 避免频繁读取布局属性
- 读取 offsetTop、getComputedStyle() 等会强制触发重排。尽量缓存这些值:
// ❌ 频繁触发重排 for (let i = 0; i < 100; i++) { console.log(element.offsetTop); // 每次循环都触发重排 } // ✅ 缓存值 const top = element.offsetTop; for (let i = 0; i < 100; i++) { console.log(top); // 仅触发一次重排 } - 使用 transform 和 opacity 实现动画
- 这两个属性不会触发重排或重绘,而是通过 GPU 加速优化性能:
/* ❌ 触发重排和重绘 */ .box { left: 100px; transition: left 0.3s; } /* ✅ 仅触发复合(Composition),性能更好 */ .box { transform: translateX(100px); transition: transform 0.3s; } - 虚拟 DOM 或文档片段(DocumentFragment)
- 在批量操作 DOM 时,先在内存中修改虚拟 DOM 或使用 DocumentFragment,最后一次性插入真实 DOM。
5.浏览器优化机制
现代浏览器会通过以下方式优化重排和重绘:
- 异步布局:浏览器将多次重排合并为一次执行(如 requestAnimationFrame)。
- 增量布局:仅对受影响的部分进行布局计算。
- 离屏渲染:将元素渲染到离屏缓冲区,减少主线程压力。
6.总结
- 重排(Reflow):改变布局,开销大,需尽量避免。
- 重绘(Repaint):仅改变外观,开销小,但仍需优化。
- 优化核心:减少 DOM 操作、批量修改样式、使用 GPU 加速属性(如 transform/opacity)。
通过合理优化,可以显著提升页面渲染性能,尤其是在动画和复杂交互场景下。
112

被折叠的 条评论
为什么被折叠?



