一、什么是回流
当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流
具体的浏览器解析渲染机制如下所示:
下面这些操作会导致回流:
- 页面的首次渲染
- 浏览器的窗口大小发生变化
- 元素的内容发生变化
- 元素的尺寸或者位置发生变化
- 元素的字体大小发生变化
- 激活CSS伪类
- 查询某些属性或者调用某些方法
- 添加或者删除可见的DOM元素
在触发回流(重排)的时候,由于浏览器染页面是基于流式布局的,所以当触发回流时,会导致周围的DOM元素重新排列,它的影响范围有两种:
- 全局范围: 从根节点开始,对整个渲染树进行重新布局
- 局部范围:对渲染树的某部分或者一个渲染对象进行重新布局
二、什么是重绘?
当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这人过程就是重绘。
下面这些操作会导致重绘:
- color、background 相关属性: background-color、background-image等。
- outline 相关属性: outline-color、 outline-width 、text-decoration
- border-radius、 visibility、 box-shadow
可以把页面理解为一个黑板,黑板上有一朵画好的小花。现在我们要把这朵从左边移到了右边,那我们要先确定好右边的具体位置,画好形状(回流),再画上它原有的颜色(重绘)
除此之外还有一些其他引起重绘行为:
- 颜色的修改
- 文本方向的修改
- 阴影的修改
注意: 当触发回流时,一定会触发重绘,但是重绘不一定会引发回流 (触发回流一定会触发重绘)
三、如何避免回流与重绘?
减少回流与重绘的措施:
- 操作DOM时,尽量在低层级的DOM节点进行操作
- 不要使用 table 布局,一个小的改动可能会使整人 table 进行重新布局
- 使用CSS的表达式
- 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式
- 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
- 避免频繁操作DOM,可以创建一个文档片段 documentFragment ,在它上面应用所有DOM操作,最后再把它添加到文档中
- 将元素先设置 display:
none操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 - 将DOM的多人读操作(或者写操作) 放在一起,而不是读写操作穿插着写。这得益干浏览器的渲染队列机制。
浏览器针对页面的回流与重绘,进行了自身的优化染队列