浏览器的回流与重绘(Reflow&Repaint)

前言:

  在了解回流与重绘之前,我们先来了解下浏览器的渲染机制:

  1. 浏览器采用的是流式布局模型(Flow Based Layout)

  2. 浏览器会把CSS解析成CSSOM Tree,把HTML解析成 DOM Tree,把这两个合并成 Render Tree

  3. 有了Render Tree 我们就知道了所有节点的位置和样式,浏览器就开始计算他们在页面中的位置,然后开始绘制

  4. 由于浏览器是流式布局,对于Render Tree的计算通常只需要遍历一遍就可以完成。但是table及其内部的元素除外,他们可能要计算多次,需要花费等同的元素3倍的时间,这也是不推荐使用table的原因。

回流(Reflow)

当Render Tree 中的部分或全部元素的尺寸,结构或者处罚某些属性时,浏览器会重新计算并渲染页面,称为回流。此时浏览器需要重新进行计算,计算后还需要重新页面布局,因此是较重的操作。

会导致回流的操作有:

  • 页面初次渲染
  • 浏览器窗口发生改变
  • 元素尺寸,位置,内容发生变化
  • 元素字体大小变化
  • 添加或者删除的可见dom元素
  • 激活CSS伪类,例如 :hover
  • 查询某些属性或调用某些方法

一些常用的会导致回流的属性或方法

  • clientWidth, clientHeight, clientTop, clientLeft
  • offsetWidth, offsetHeight, offsetTop, offsetLeft
  • scrollWidth, scrollHeight, scrollTop, scrollLeft
  • scrollIntorView(), scrollInToViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTop
  • ...

重绘(Repaint)

当元素的样式改变不影响布局时(例如:color, background-color, visibility等),浏览器将使用重绘对元素进行更新,此时由于只需要对UI层面重新绘制,因此损耗较少

回流一定会导致重绘,但是重绘不一定会导致回流

如何避免:

CSS

  • 避免使用table布局
  • 尽可能在DOM树的最末端改变class
  • 避免设置多层内联样式
  • 避免CSS表达式

JavaScript

  • 避免频繁的操作样式,最好一次性写好style属性,或者将样式定义为calss,并一次性更改class属性
  • 避免频繁操作DOM,创建一个 documentFragment ,这这个上面应用所有的DOM操作,最后再把它添加到文档中
  • 也可以先设置为display:none; 操作结束后再把它显示出来,因为在dispkay属性为none的元素上进行DOM操作不会引起回流和重绘
  • 避免频繁读取引发回流、重绘的属性,如果要多次使用,建议先把它缓存起来
  • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
原文地址:https://www.cnblogs.com/shenjp/p/13535552.html