1、浏览器的渲染过程

想清楚的理解回流与重绘之前, 要先清楚的理解浏览器的渲染过程是怎么样的。

浏览器的渲染过程大致如下:

  1. 构建DOM树和CSSOM树: 解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM树
  2. 构建渲染树: 将 DOM树 和 CSSOM树结合,生成渲染树(Render Tree)
  3. 布局: 渲染树的每个元素包含的内容都是计算过的,它被称之为布局(layout)。浏览器使用一种流式处理的方法,只需要一次绘制操作就可以布局所有的元素
  4. 绘制: 将渲染树的各个节点绘制到屏幕上,这一步被称为绘制(painting) alt

2、回流(reflow)与重构(repaint)

回流

回流又称重排,当浏览器发现布局(layout)发生了变化,这个时候就需要倒回去重新渲染,这个过程叫 回流(reflow)。回流几乎是无法避免的,因为只要用户进行了交互操作,就会发生页面的一部分重新渲染。

会发生回流的情况如下:

  1. 页面的第一次渲染(初始化)
  2. DOM树的变化(如:增删节点)
  3. Render树的变化(如:padding 改变)
  4. 浏览器窗口的尺寸变化 resize
  5. fontsize的变化
  6. 获取元素的某些属性

重绘

重绘(repaint)则是当我们改变某个元素的背景色,文字颜色,边框颜色等不影响它周围或内部布局的属性是,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变。

会发生重绘的情况如下: 背景色、颜色的改变等会引起重绘(repaint)

回流与重绘的区别

  • 当元素的位置或者几何尺寸发生改变时会触发回流,
  • 当背景色和颜色的改变会引起重绘,

注意:回流一定会发生重绘,而重绘不一定发生回流!

display、visibility

  • display:none 会触发回流(reflow)
  • visibility:hidden 属性表示隐藏元素,元素任然占据着布局空间,并没有改变布局和几何尺寸,所以只会触发重绘(repaint)

3、减少回流与重绘(性能优化)

为了优化性能,我们需要减少回流、重绘的触发次数

  1. 用 transform 做形变和位移可以减少回流
  2. 避免逐个修改节点样式,尽量一次性修改
  3. 可以将需要多次修改的 DOM 元素设置 display:none ,操作完再显示(因为隐藏元素不在 render 树内,因此修改隐藏元素不会触发回流重绘)
  4. 避免多次读取某些属性
  5. 通过绝对位移将复杂的节点元素脱离文档流,形成新的 Render Layer,降低回流成本