在前端开发中,尤其是在处理网页的与渲染时,“回流”(Reflow)和“重”(Repaint)是两个至关重要的概念。这两个过程在浏览器渲染页面时发挥着重要的作用,但它们有着不同的触发条件和性能影响。下面将详细解释这两个概念及其差异。
回流重绘对于lighthouse评分的影响,可以参考我们这篇文章《优化性能:回流与重绘对Lighthouse指标的影响》

回流(Reflow)
回流是指浏览器重新计算元素的几何属性(如宽度、高度、位置等)的过程。当页面的布局发生变化时,例如:
- 改变元素的尺寸(如通过修改
width或height)。 - 改变元素的位置(如通过修改
margin或padding)。 - 添加或删除DOM元素。
- 修改元素的内容或样式(如更改字体大小)。
一旦这些变化发生,浏览器需要重新计算页面的布局,这就是回流。在回流过程中,浏览器会通过中心化模型重新计算所有相关元素的位置和大小,确保页面的布局能够反映这些更改。
回流是一个成本较高的操作,特别是在页面包含大量DOM元素时,频繁的回流会导致性能下降,影响用户体验。

重绘(Repaint)
重绘是指浏览器重新绘制元素的过程,通常是因为元素的样式发生了变化,但不会影响其几何属性。重绘的典型情况包括:
- 修改元素的颜色(如
color、background-color)。 - 修改阴影、边框等视觉效果。
与回流不同,重绘不会影响其他元素的布局,因此其开销相对较小。不过,如果一个元素发生了重绘,而该元素又影响到多个子元素的视觉表现,可能会导致很多元素都需要被重绘,从而影响性能。
回流与重绘的关系
回流和重绘是相互关联的过程,当发生回流时,通常也会引发重绘。具体来说,如果一个元素的尺寸或位置发生变化,浏览器首先会进行回流来更新布局,然后再执行重绘来更新元素的视觉效果。
但反之则不成立,重绘不会导致回流。优化网页性能时,开发者应该尽量减少回流的次数,避免在JavaScript中频繁操作DOM,特别是影响布局的操作。以下是一些优化回流的技巧:
- 将DOM变化集中到一起,尽量减少对DOM的多次操作。
- 使用
display: none隐藏元素,使其不参与布局计算。 - 使用
documentFragment等方法批量操作DOM。

如何避免回流和重绘
为了优化网页的性能和响应速度,开发者应该尽量减少回流和重绘的次数。接下来,我们将探讨一些实用的方法和策略,帮助你有效避免回流和重绘。
1. 批量处理DOM操作
-
集中更新:尽量将多个DOM操作集中在一起进行,而不是分散在不同的操作中。例如,如果要对多个元素应用样式变化,应该将其合并为一次操作,而不是逐一修改。
-
使用文档片段:可以使用
document.createDocumentFragment()创建一个文档片段,将多个DOM节点添加到这个片段中,最后一次性将片段插入到实际的DOM中,这样可以减少回流和重绘的次数。
2. 减少复杂的布局计算
-
避免使用CSS属性触发回流:如
offsetWidth、offsetHeight、getComputedStyle()等避免频繁调用,特别是在动画或循环中,因为它们会强制浏览器计算布局。 -
使用绝对定位:对于不需要参与文档流的元素,可以使用
position: absolute或position: fixed,可以减少回流的发生,因为它们不会影响其他元素。
3. 用CSS进行动画效果
- 利用CSS过渡和动画:CSS过渡(
transition)和动画(animation)通常在GPU中运行,并且不涉及回流。这使得它们比通过JavaScript实现的动画更加高效。尽量使用transform和opacity等属性,这些属性的变更通常不会引发回流。
4. 避免频繁的样式计算
-
缓存计算结果:如果需要多次使用某个计算结果,存储在变量中并使用它,而不是每次都重新计算。例如,获取某个元素的高度时,第一次计算后,将结果缓存,后续操作直接使用cached值。
-
使用CSS类进行样式变化:通过添加或移除CSS类,而不是直接修改元素样式,可以减少JavaScript对DOM的直接操作。例如,使用
classList来切换类名。
5. 结构优化
-
合理的DOM结构:保持DOM结构的扁平化可以减少回流的复杂性,避免嵌套过深的元素,确保元素之间的关系简明清晰。
-
懒加载:对于不需要立即展示的元素,可以使用懒加载(Lazy Loading)技术,延迟元素的加载,减少初始渲染所需的回流和重绘。
6. 使用虚拟DOM
- 框架优化:现代框架(如React、Vue等)使用虚拟DOM来优化渲染性能。开发者可以利用这些框架,减少直接对真实DOM的操作,从而降低回流和重绘的频率。
7. 监测和分析性能
- 使用浏览器开发者工具:浏览器内置的开发者工具可以帮助开发者监测回流和重绘的发生。通过使用性能分析功能,可以识别引起性能问题的代码,从而进行优化。

资源加载(图片/视频等)对回流和重绘的影响
影响回流的方式
- 占位计算:当网页中的图片或视频资源未加载完成时,浏览器无法确定它们的最终尺寸。如果不为这些资源设置明确的宽度和高度,浏览器在加载完成后可能会触发回流,以重新计算页面布局,因为它需要重新安排其他元素的位置。
- 插入新元素:当图片或视频被动态加载到页面中(例如,通过JavaScript动态添加),这会导致浏览器需要重新计算布局,从而引发回流。
影响重绘的方式
- 样式变化:当图片或视频加载完成并显示出来时,可能会引发重绘,特别是当其样式(如透明度、滤镜等)发生变化时。浏览器需要重新绘制相应的元素及其相关的子元素。
如何处理资源加载对回流和重绘的影响
为减少资源加载期间对回流和重绘的影响,可以采取以下策略:
1. 预设尺寸
- 设置宽度和高度:在HTML中为图片和视频元素设置
width和height属性,或者通过CSS明确设置它们的尺寸。这样可以确保浏览器在渲染时保留空间,避免在资源加载后触发回流。
<img src="image.jpg" width="600" height="400" alt="示例图片">
2. 使用占位符
- 占位符图片:在实际加载的图片或视频之前,先展示一个占位符(例如,低分辨率图像或加载动画),从而减少回流的频率。
3. 懒加载
- 懒加载技术:对于页面不在可视区域的图片或视频,可以使用懒加载,延迟加载这些资源,直到用户滚动到相应的位置。这减少了初始加载时的回流和重绘。
<img src="placeholder.jpg" data-src="image.jpg" class="lazyload" alt="示例图片">
使用JavaScript或其他库(如Intersection Observer API)在用户滚动到图片位置时动态加载真实的图片。
4. 按需加载和异步加载
-
按需加载:对于内容较多的页面,可以按需加载(如分页加载),仅在用户需要时加载特定资源,减少初始负担和回流。
-
异步加载:对于JavaScript文件可以使用
async或defer属性,使其异步执行,避免阻塞渲染,从而减少回流的发生。
5. 优化CSS和JavaScript
-
减少重绘触发:在进行DOM操作时,尽量批量修改并使用类替换的方法,避免逐个设置元素的样式,降低重绘的数量。
-
使用transform而不是top/left:在应用动画时,使用CSS的
transform属性(如translate)而不是直接修改top或left,因为transform不会触发回流。