回流(Reflow)和重绘(Repaint)是浏览器渲染页面时的关键步骤,对性能优化至关重要。以下是它们的核心要点:
1. 回流(Reflow)
- 定义:当元素的布局属性(如尺寸、位置、结构等)发生变化时,浏览器需要重新计算元素的几何信息,并调整页面布局的过程。
- 触发条件:
- 改变窗口大小
- 修改元素尺寸(宽、高、边距等)
- 增删可见的DOM元素
- 调整字体或内容变化
- 激活CSS伪类(如
:hover
) - 读取布局属性(如
offsetTop
、scrollWidth
等,可能导致强制同步布局)
- 性能消耗:高,可能引发整个渲染树重新计算。
2. 重绘(Repaint)
- 定义:当元素的外观属性(如颜色、背景、边框等)发生变化,但不影响布局时,浏览器重新绘制元素的过程。
- 触发条件:
- 修改颜色、背景色、边框颜色等
- 调整透明度(
opacity
) - 改变可见性(
visibility
)
- 性能消耗:较低(不涉及布局计算)。
3. 关键区别
- 回流必然导致重绘:布局变化通常需要重新绘制。
- 重绘不一定触发回流:仅外观变化且不影响布局时。
4. 优化策略
- 减少DOM操作:
- 使用
DocumentFragment
批量操作DOM。 - 避免逐行修改样式,改用
class
或cssText
。
- 使用
- 避免强制同步布局:
- 避免在修改样式后立即读取布局属性(如
offsetTop
),这会强制浏览器提前回流。 - 使用变量缓存布局属性值。
- 避免在修改样式后立即读取布局属性(如
- 脱离文档流:
- 对动画元素使用
position: absolute/fixed
,减少布局影响范围。
- 对动画元素使用
- 利用CSS3特性:
- 使用
transform
和opacity
实现动画(触发合成层,跳过回流和重绘)。 - 启用GPU加速(如
will-change: transform
)。
- 使用
- 优化渲染流程:
- 避免使用
table
布局(局部变化可能引发全局回流)。 - 使用
requestAnimationFrame
替代setTimeout
处理动画。
- 避免使用
5. 浏览器渲染流程
- 解析:生成DOM树和CSSOM树。
- 合并:构建渲染树(Render Tree)。
- 布局(回流):计算元素的位置和尺寸。
- 绘制(重绘):填充像素到屏幕。
- 合成:将各图层合并显示。
示例
// 不推荐:多次触发回流
element.style.width = '100px';
element.style.height = '200px';
// 推荐:合并修改(一次回流)
element.style.cssText = 'width: 100px; height: 200px;';
总结:优化核心在于减少回流次数和范围,优先使用不影响布局的样式修改,合理利用浏览器渲染机制提升性能。