深入理解网页的回流与重绘:原理、触发因素

0 阅读5分钟

在前端开发中,网页的性能优化是一个至关重要的话题。其中,回流(重排)和重绘是影响网页性能的两个关键概念。了解它们的原理、触发因素以及如何优化,对于提高网页的响应速度和用户体验至关重要。本文将结合代码示例和详细解释,深入探讨回流和重绘的相关知识。

布局难点与列式布局

块级格式化上下文(BFC)

在 HTML 中,根元素是最外层的第一个 BFC 元素。BFC 即块级格式化上下文,它规定了块级元素从上到下排列,行内元素从左到右排列,形成了文档流的基本规则。一些属性如 floatoverflow: hiddenflex 可以创建 BFC。

列式布局与 table 标签

table 标签可以用于列式布局,通过 tr(行)和 td(列)来构建表格结构。然而,使用 table 进行布局并不推荐,主要原因有以下几点:

  • 触发大量回流和重绘table 中局部的改变会触发整个 table 的回流重排,就像“火烧赤壁”一样,一个小的变动可能会影响整个布局。
  • 语义不符table 标签主要用于展示数据表,使用它进行布局不符合其语义,不利于代码的维护和理解。
  • 不够灵活table 的布局相对固定,不够灵活,难以满足复杂的页面设计需求。

回流(重排)Reflow

定义

当 RenderTree 中部分或全部元素的尺寸、结构或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程叫做回流,也称为重排。

回流简单示例:

屏幕录制 2025-07-02 142937.gif

当我们点击按钮将宽度修改了,就是改变了元素的布局,这样就是触发了回流,而且触发了回流就一定也会触发重绘。

触发回流的方式

  1. 页面首次渲染:严格意义上来说,这不是典型的回流,但它是从无到有的渲染过程,是最耗时的操作。据统计,网页每慢 0.1 秒,可能会少 1000 万的收入,因此页面首次渲染的性能优化至关重要。
  2. 浏览器窗口大小改变:当用户调整浏览器窗口大小时,页面中的元素需要重新计算布局,以适应新的窗口尺寸,从而触发回流。
  3. 元素尺寸或位置改变:例如,通过 CSS 改变元素的宽度、高度、边距等属性,或者使用 JavaScript 移动元素的位置。不过,transitiontransformopacity 在新图层中的变化除外,它们不会触发回流。
  4. 元素内容变化:当使用 appendChildremoveChild 方法添加或删除元素时,会导致页面结构发生变化,从而触发回流。
  5. display 属性改变:将元素的 display 属性从 none 改为 block 或反之,会使元素在文档流中显示或隐藏,触发回流。
  6. 字体大小变化:改变元素的字体大小会影响元素的尺寸,从而触发回流。
  7. 激活 CSS 伪类:例如,当鼠标悬停在元素上激活 :hover 伪类时,浏览器需要重新计算元素的样式,可能会触发回流。
  8. 查询某些属性或调用某些方法:例如,调用 img.getBoundingClientRect() 方法会触发回流,因为浏览器需要获取元素的精确位置和尺寸信息。

代码示例中的回流优化

使用 display: none 可以避免元素参与回流和重绘,这是一种常见的性能优化方案。

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>table 布局,不推荐</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: red;
            margin: 10px;
        }
       .vis_hid{
            visibility: hidden;
        }
        .dis_none{
            display: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="box vis_hid">123</div>
        <div class="box dis_none">456</div>
    </div>
</body>
</html>

在这个示例中,classdis_none 的元素使用了 display: none,该元素不会参与回流和重绘,从而提高了页面的性能。

重绘 Repaint

定义

当页面元素的样式改变,但不影响其在文档流中的位置时,浏览器会进行重绘操作。例如,改变元素的颜色、背景颜色、可见性等属性。

重绘简单示例:

屏幕录制 2025-07-02 161022.gif

代码示例中的重绘

在上述代码示例中,classvis_hid 的元素使用了 visibility: hidden,该元素会被隐藏,但仍然占据文档流中的位置,只会触发重绘,而不会触发回流。

页面渲染流程

输入 URL 到页面渲染的过程

  1. 下载 HTML:浏览器根据输入的 URL 下载 HTML 文件,首先获取字节数据,然后将其解码为 UTF - 8 编码的 HTML 字符,接着解析 HTML 的开关标签和属性,构建节点对象,最终构建 DOM 树。
  2. 下载 CSS:如果 HTML 中包含 link 标签引用的 CSS 文件,浏览器会下载 CSS 文件。下载过程包括获取字节码,根据 Content - Type 确定文件类型为 text/css,解码为 UTF - 8 编码的 CSS 文本,进行词法分析得到 token,构建 CSS 规则节点,最终形成 CSSOM 树。
  3. 构建 RenderTree:将 DOM 树和 CSSOM 树合并,形成 RenderTree,它只包含需要显示的元素及其样式信息。
  4. Layout 树:进行布局计算,确定元素在文档流中的位置和大小,形成 Layout 树。
  5. 图层处理:根据元素的 z - indexposition: fixedtransition + transform / opacity 等属性,将元素分配到不同的图层中。例如,使用 translate(50%,50%,50%) 可以利用 GPU 加速,提高渲染性能。
  6. 图层合并:将各个图层合并,最终由浏览器的渲染引擎在绘制平面上进行像素点绘制,完成页面的渲染。

总结

回流和重绘是影响网页性能的重要因素,在前端开发中,我们应该尽量减少回流和重绘的次数,以提高网页的响应速度和用户体验。通过合理使用 CSS 属性、优化 DOM 操作以及了解页面渲染流程,我们可以更好地进行性能优化。希望本文能帮助你深入理解回流和重绘的相关知识,并在实际开发中应用这些优化策略。