重绘(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 和样式的修改),并减少对一些样式信息的请求,尽量利用好浏览器的优化策略。
- 添加 css 样式而不是利用js控制样式
- 尽量将需要改变 DOM 的操作一次完成
-
用translate替代top改变(因为top会触发回流,但是translate不会)
-
使用 visibility 替换 display: none
- 不要一条一条的修改dom样式,预先定义好class,然后修改dom的className
-
不要使用table布局,可能很小的一个改动,会造成table的重新布局
-
requestAnimationFrame
-
CSS 选择符从右往左匹配查找,避免节点层级过多
- 将需要多次重排的元素,position 属性设为 absolute 或 fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位;
-
把一些重绘回流频繁的dom元素,独立到一个图层上,去控制重绘回流的范围
-
避免使用触发重绘、回流的css属性
- 把dom离线后修改,比如:先把dom给display:none(有一次reflow),然后你修改100次,然后再把它显示出来
- 不要把dom节点的属性值放在一个循环里,当成循环的变量(offsetHeight,offsetWidth,获取dom的真实位置,就会进行回流)
- 动画实现的速度的选择(频繁的动画重绘回流,会导致cpu资源的疯狂损耗,导致网页性能的损耗,导致js代码执行收到UI渲染线程的阻塞)
- 对于动画,新建图层(保证回流重绘的影响面较小)
- 启用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较低且包含一个复合层的兄弟元素(即该元素在复合层上面渲染)