回流
当元素的几何属性发生变化,浏览器需要重新计算元素的位置和几何信息,更新渲染树和页面布局的过程
触发条件
- 改变窗口大小
- 修改元素尺寸(
width
/height
/padding
/margin
/border
) - 调整元素位置(
position
/top
/left
/float
) - 内容变化(文本增减、图片加载)
- 增删可见的 DOM 元素
- 激活 CSS 伪类(如
:hover
) - 读写
offsetWidth
/scrollTop
等布局属性(会强制触发同步回流)
特点
- 性能消耗高:回流可能导致整个文档或部分 DOM 树的重新布局。
- 级联性:一个元素回流可能引发其父级、子级或兄弟元素回流(例如父容器宽度变化)。
重绘
当元素的非几何样式(如颜色、背景、阴影等)发生变化,但不影响布局时,浏览器根据新的样式信息重新绘制元素的外观。
触发条件
- 修改颜色(
color
/background-color
) - 调整透明度(
opacity
) - 改变文本样式(
font-family
/text-decoration
) - 更新边框样式(
border-style
/box-shadow
)
特点
- 性能消耗较低:不涉及布局计算,仅重新绘制像素。
- 依赖回流:重绘一定发生在回流之后(布局未变,但外观变化)。
性能优化
1. 减少回流次数:
- 合并多次样式修改(使用
class
或cssText
批量操作)。 - 避免逐行读取布局属性(如
offsetHeight
),或通过变量缓存读取结果。 - 使用
transform
/opacity
等属性触发 GPU 加速(跳过回流和重绘,直接进入合成阶段)。
javascript
// 低效:触发多次回流
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
// 高效:合并为一次操作
element.style.cssText = 'width:100px; height:200px; margin:10px;';
// 或通过 class 批量修改
element.classList.add('new-style');
2. 缩小回流范围
- 对频繁操作的元素使用
position: absolute/fixed
,使其脱离文档流,减少影响范围。 - 在需要对多个元素进行批量操作时,可以将这些操作放在一个虚拟容器
DocumentFragment
中,最后再插入到 DOM 树中,减少回流和重绘的次数
总结
- 回流必然导致重绘,重绘不一定触发回流。
- 性能优先级:减少回流 > 减少重绘 > 减少合成。