重绘(paint) :

render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不影响布局的,比如background-color,则称为重绘。

回流(layout):

render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。当页面布局和几何属性改变时就需要回流,它会重新的渲染HTML的渲染树。

 

回流必定会发生重绘,重绘不一定会引发回流

回流发生条件:

  • 页面的初始加载
  • 更改整个浏览器的窗口大小(resize 事件发生时)
  • 修改HTML的字体大小
  • 添加或者删除可见的 DOM 元素
  • 元素内容变化(比如文本改变或者图片大小改变而引起的计算值宽度和高度改变)
  • 功能性伪类触发

触发页面回流属性: 

width, height, padding, margin, display, border-width, border, min-height

top, bottom, left, right, position, float, clear

text-align, overflow-y, font-weight, overflow, font-family, line-height, vertical-align, white-space, font-size

触发重绘的属性:

color, border-style, border-radius, visibility, text-decoration, background, background-image, background-position,  background-repeat, background-size,

outline-color, outline-style, outline-width, box-shadow

如何减少回流和重绘?

减少回流和重绘其实就是需要减少对 render tree 的操作(合并多次多 DOM 和样式的修改),并减少对一些样式信息的请求,尽量利用好浏览器的优化策略。

  1. 添加 css 样式而不是利用js控制样式
  2. 尽量将需要改变 DOM 的操作一次完成
  3. 用translate替代top改变(因为top会触发回流,但是translate不会)

  4. 使用 visibility 替换 display: none 

  5. 不要一条一条的修改dom样式,预先定义好class,然后修改dom的className
  6. 不要使用table布局,可能很小的一个改动,会造成table的重新布局

  7. requestAnimationFrame

  8. CSS 选择符从右往左匹配查找,避免节点层级过多

  9. 将需要多次重排的元素,position 属性设为 absolute 或 fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位;
  10. 把一些重绘回流频繁的dom元素,独立到一个图层上,去控制重绘回流的范围

  11. 避免使用触发重绘、回流的css属性

  12. 把dom离线后修改,比如:先把dom给display:none(有一次reflow),然后你修改100次,然后再把它显示出来
  13. 不要把dom节点的属性值放在一个循环里,当成循环的变量(offsetHeight,offsetWidth,获取dom的真实位置,就会进行回流)
  14. 动画实现的速度的选择(频繁的动画重绘回流,会导致cpu资源的疯狂损耗,导致网页性能的损耗,导致js代码执行收到UI渲染线程的阻塞)
  15. 对于动画,新建图层(保证回流重绘的影响面较小)
  16. 启用GPU硬件加速( 在使用位置变化的时候,translate(3d),会使用Gpu的运算能力,gpu是并行运算的)

css性能让JavaScript变慢?

一个线程 --> JavaScript解析

一个线程 --> UI渲染

当我们通过 JS 操作 DOM 的时候,其实这个操作涉及到了两个线程之间的通信,那么势必会带来一些性能上的损耗。操作 DOM 次数一多,也就等同于一直在进行线程之间的通信,并且操作 DOM 可能还会带来重绘回流的情况,所以也就导致了性能上的问题。浏览器规定,UI线程和JavaScript线程是互斥的,当UI线程在渲染时,JavaScript线程没有执行,被冻结的。JavaScript代码被执行时,UI线程是被冻结的。频繁触发重绘和回流,会导致UI频繁渲染,最终导致js变慢。

 

新建dom的过程:

 

  1.获取dom后分割为多个图层

 

  2.对每个图层的节点计算样式结果(recalculate style—样式重计算)

 

  3.为每个节点生成图形和位置(layout—回流和重布局)

 

  4.将每个节点绘制填充到图层位图中(paint setup和paint —重绘)

 

  5.图层作为纹理上传至GPU

 

  6.符合多个图层到页面上生成最终屏幕图像(Composite layers—图层重组)

 

如何将dom元素变成新的独立图层?

注意:新建图层能减少重绘回流的消耗,但是绘增加图层合成的消耗。所以,图层(layers)不能被烂用。

chrome创建图层的条件

  1.3D或透视变换css属性(perspective ,transfrom)

  2.使用加速视频解码的<video>节点

  3.拥有3D(WebGL)上下文或加速的2D上下文的<canvas>节点

  4.混合插件(如flash)

  5.对自己的opacity做css动画或使用一个动画webkit变换的元素

  6.拥有加速css过滤器的元素

  7.元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)

  8.元素有一个z-index较低且包含一个复合层的兄弟元素(即该元素在复合层上面渲染)