浏览器的回流和重绘及其优化方式

推荐了解的知识:基本的HTML,基本的JavaScript,以及一些css工做原理方面的知识css

浏览器的渲染原理

  • css的加载和解析不会阻塞html文档的解析
  • css的解析会阻塞js的执行,必须等到CSSOM生成后才能执行js
  • js的执行会阻塞html文档的解析
  • html一边解析一边显示
  • css必须彻底解析完毕才能进入生成渲染树环节
           浏览器向服务器请求到了HTML文档后便开始解析,产物是DOM Tree(文档对象模型),若是有css,会根据css生成CSSOM(CSS对象模型),而后再由DOM和CSSOM合并产生Render Tree渲染树,有了渲染树,知道了全部节点的样式,便根据这些节点以及样式计算它们在浏览器中确切的大小和位置,这就是布局。最后把节点绘制到浏览器上。

clipboard.png

建立DOM树—建立CSSOM树—执行脚本—生成渲染树—生成布局—绘制html

回流

       回流(reflow)当render tree中的一部分(或所有)由于元素的规模尺寸,布局,隐藏等改变时,网络浏览器从新渲染部分或所有文档的过程。node

重绘

       当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行从新绘制操做。浏览器

       由于回流(reflow)在浏览器中属于一种用户主导的模块化操做,因此知道如何去改进回流(reflow)时间以及知道各类文档属性(DOM节点深度,css的渲染效率,各类各样的样式改变)对回流(reflow)时间的影响对于开发人员讲是颇有帮助的。有时候,即便仅仅回流一个单一的元素,也可能要求它的父元素以及任何跟随它的元素也产生回流。性能优化

什么时候发生

       有大量的用户行为以及潜在的DHTML改变会触发回流(reflow)。例如,改变浏览器窗口的大小,使用一些JavaScript方法,包括计算样式,对DOM进行元素的添加或删除,或是改变元素的class等。服务器

  1. 添加或者删除可见的DOM元素;
  2. 元素位置改变;
  3. 元素尺寸改变——边距、填充、边框、宽度和高度
  4. 内容变化,好比用户在input框中输入文字,文本或者图片大小改变而引发的计算值宽度和高度改变
  5. 页面渲染初始化
  6. 浏览器窗口尺寸改变——resize事件发生时
  7. 计算 offsetWidth 和 offsetHeight 属性
  8. 设置 style 属性的值

       回流必将引发重绘,而重绘不必定会引发回流。网络

性能优化

       回流比重绘的代价要更高,回流的花销跟render tree有多少节点须要从新构建有关系;浏览器自己可以进行优化,尽量减小重绘和回流。
       若是每行JS代码操做DOM都须要回流重绘的话,浏览器可能就会受不了。因此不少浏览器都会优化这些操做,浏览器会维护1个队列,把全部会引发回流、重绘的操做放入这个队列,等队列中的操做到了必定的数量或者到了必定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让屡次的回流、重绘变成一次回流重绘。
       当你请求向浏览器请求一些 style信息的时候,就会让浏览器flush队列,好比:app

  1. offsetTop, offsetLeft, offsetWidth, offsetHeight
  2. scrollTop/Left/Width/Height
  3. clientTop/Left/Width/Height
  4. width,height
  5. 请求了getComputedStyle(), 或者 IE的 currentStyle

       当你请求上面的一些属性的时候,浏览器为了给你最精确的值,须要flush队列,由于队列中可能会有影响到这些值的操做。即便你获取元素的布局和样式信息跟最近发生或改变的布局信息无关,浏览器都会强行刷新渲染队列。模块化

如何减小回流、重绘

var s = document.body.style; 

s.padding = "2px"; // 回流+重绘

s.border = "1px solid red"; // 再一次 回流+重绘

s.color = "blue"; // 再一次重绘

s.backgroundColor = "#ccc"; // 再一次 重绘

s.fontSize = "14px"; // 再一次 回流+重绘

// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));

///能够看到每次DOM元素的样式操做都会引起重绘,若是涉及布局还会引起回流。

一. CSS中避免回流wordpress

  1. 尽量在DOM树的最末端改变class
  2. 避免设置多层内联样式
  3. 动画效果应用到position属性为absolute或fixed的元素上
  4. 牺牲平滑度换取速度
  5. 避免使用table布局
  6. 避免使用CSS的JavaScript表达式

二. JS操做避免回流

  1. 避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
  2. 避免循环操做DOM。建立一个documentFragment或div,在它上面应用全部DOM操做,最后再把它添加到window.document。
  3. 也能够在一个display:none的元素上进行操做,最终把它显示出来。由于display:none上的DOM操做不会引起回流和重绘。
  4. 避免循环读取offsetLeft等属性。在循环以前把它们存起来。
  5. 绝对定位具备复杂动画的元素。绝对定位使它脱离文档刘,不然会引发父元素及后续元素大量的回流。

参考文章:回流与重绘:CSS性能让JavaScript变慢?
参考文章:浏览器的重绘(repaints)与重排(reflows)

相关文章
相关标签/搜索