CSS-回流(reflow)与重绘(repaint)
什么是回流(重排)和重绘?
1、回流:渲染树中的一部分或全部元素的尺寸、布局、隐藏等属性改变时,会引起渲染树重新构建,这就叫回流(reflow),也叫重排。比如调整窗口大小、设置字体大小、dispaly、获取实时属性offset系列、用户在input输入、激活CSS伪类:hover等等。
2、重绘:当一些元素的可见性发生变化时,会引起重绘。比如outline、visibility、backgound-color等的变化。
3、第一次渲染时一定会有回流和重绘。回流一定会引起重绘,重绘不一定引起回流。
三个演示渲染过程的视频:
http://www.youtube.com/watch?v=nJtBUHyNBxs
http://www.youtube.com/watch?v=ZTnIxIA5KGw
http://www.youtube.com/watch?v=dndeRnzkJDU
如何减少回流(reflow)、重绘(repaint)?
- 一、 CSS中避免回流、重绘或将它们的性能影响降到最低
1.尽可能在DOM树的最末端改变class。节点越靠前,回流影响的性能消耗越大。
2.避免设置多层内联样式
3.复杂动画效果应用到position属性为absolute或fixed的元素上,这些元素不影响其他元素,只是这些元素进行重新绘制。可以避免引起父元素以及后续元素的频繁回流。
4.避免使用table布局。因为表格中任意一个小变化都会导致表格内的其他节点回流
5.使用css3硬件加速,不会引起回流重绘
常见的可以触发硬件加速的属性:
1 | transform |
- 二、 JS操作避免回流、重绘
1、假设要多次操作dom,应该在当前DOM树之外重新设置一个子树,全部操作完毕后再插入或替换DOM树的节点
e.g.:
1 | cosnt childNode = document.createElement(div); |
2.避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
e.g.:
1 | const ele = document.getElementById('app'); |
3.先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
4.避免循环读取offsetLeft等属性,在循环之前把它们存起来。下面这些属性会引起回流
1 | offsetLeft/Top/Right/Bottom |
使用举例:
1 | ele.offsetTop += 1; |
5.对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流
动画性能调试方法(以chrome为例):