重绘与重排

312 阅读3分钟

重排

  • 当render tree中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变时,浏览器重新渲染部分DOM或全部DOM的过程。回流也被称为重排,其实从字面上来看,重排更容易让人形象易懂(即重新排版整个页面)。
  • 回流必将引起重绘,而重绘不一定会引起回流。
  • 重排也叫回流,实际上,reflow的字面意思也是回流,之所以有的叫做重排,也许是因为重排更好理解,更符合中国人的思维。标准文档之所以叫做回流(Reflow),是因为浏览器渲染是基于“流式布局”的模型,流实际就使我们常说的文档流,当dom或者css几何属性发生改变的时候,文档流会受到波动联动的去更改
  • 引起重排的操作有
    1. 浏览器窗口大小发生改变。
    2. 元素尺寸或位置发生改变。
    3. 元素内容变化(文字数量或图片大小等等)。
    4. 元素字体大小变化。
    5. 添加或者删除可见的DOM元素。
    6. 激活CSS伪类(例如::hover)。
    7. 设置style属性
    8. 查询某些属性或调用某些方法。
    9. 页面首次渲染。

重绘

  • 当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
  • 当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作

如何减少回流,重绘?

CSS中避免回流、重绘

  1. 尽可能在DOM树的最末端改变class
  2. 避免设置多层内联样式
  3. 动画效果应用到position属性为absolute或fixed的元素上
  4. 避免使用table布局
  5. 使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘.

JS操作避免回流、重绘

  1. 避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
  2. 避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中
  3. 先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
  4. 避免循环读取offsetLeft等属性,在循环之前把它们存起来
  5. 对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流

总结

回流在浏览器中属于一种用户主导的操作,所以知道如何去改进回流时间以及知道各种文档属性(DOM节点深度,css的渲染效率,各种各样的样式改变)对回流时间的影响对于前端开发来讲是很有帮助的。有时即便是回流一个单一的元素,也可能要求它的父元素以及任何跟随它的元素也产生回流。例如需要改变某个元素的背景,这就不涉及该元素的属性,所以只发生重绘。