之前看过这样一篇文章:
先来看一段代码
width: 150px;
height: 150px;
font-size: 24px;
position: absolute;
当浏览器解析到
position
的时候,发现该元素是绝对定位,需要脱离文档流,但是之前的属性都是按照常规解析的,所以不得不重新渲染,这时渲染引擎就系要接触该元素再文档中的占位,这样就有可能导致其他元素受到他的回流影响进而发生重排。
调整后代码
position: absolute;
width: 150px;
height: 150px;
font-size: 24px;
根本原因: reflow(回流)
其实是该元素回流导致,减少浏览器
reflow(回流)
,就可以提升浏览器渲染dom的性能
那么问题来了?到底怎样才可以减少reflow(回流)
呢?
要尽量避免,那就需要知道浏览器的渲染过程!
- 解析html构建dom树,解析css构建css树:将html解析成树形的数据结构,将css解析成树形的数据结构
- 构建生成render树:DOM树和CSS树合并之后形成的render树。
- 排版布局render树:有了render树,浏览器已经知道那些网页中有哪些节点,各个节点的css定义和以及它们的从属关系,从而计算出每个节点在屏幕中的位置。
- 绘制渲染render树:按照计算出来的规则,通过显卡把内容画在屏幕上。
css代码从解析到显示到浏览器屏幕上,其实就是上面的2->3->4的过程。
- 浏览器并不是一获取到css样式就立即解析,而是根据css样式的书写顺序,将其对应dom树的结构而分布render样式,与DOM树合并完成并生成render树,也就是上面的第2步。
- 然后遍历render树每个结点的css样式进行解析,此时的css样式的遍历顺序完全是按照之前的书写顺序。在解析过程中,一旦浏览器发现某个元素的定位变化影响布局,则需要倒回去重新渲染。就会导致第3步占用的时间过长,直接影响到了第4步的显示。
这里有一个规范,建议顺序大致如下:
1、定位属性:
position、display、float、left、top、right、bottom、overflow、clear、z-index
2、自身属性:
width、height、padding、border、margin、background
3、文字样式:
font-family、font-size、font-style、font-weight、font-varient、color
4、文本属性:
text-align、vertical-align、text-wrap、text-transform、text-indent、text-decoration、letter-spacing、word-spacing、white-space、text-overflow
5、CSS3 中新增属性:
content、box-shadow、border-radius、transform
减少reflow对性能的影响的建议
- 不要一条一条地修改 DOM 的样式,预先定义好 class,然后修改 DOM 的 className
- 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改100次,然后再把它显示出来
- 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
- 尽可能不要修改影响范围比较大的 DOM
- 为动画的元素使用绝对定位 absolute / fixed
- 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
扩展
repaint(重绘):
是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。这个过程就是重绘。重排必定会引发重绘,但重绘不一定会引发重排
常见引发重绘的属性:
color、border-style、visibility、background、text-decoration、background-image、background-position、background-repeat、outline-color、outline、outline-style、border-radius、outline-width、box-shadow、background-size
减少repaint对性能的影响的建议
- 不要一条一条地修改 DOM 的样式。可以先定义好 css 的 class,然后修改 DOM 的 className。
- 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。
- 为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。
- 千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。(table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花2~3倍于同等元素的时间。这也是为什么我们要避免使用table做布局的一个原因。)
- 不要在布局信息改变的时候做查询(会导致渲染队列强制刷新)
- 用translate替代top改变
- 用opacity替代visibility(在独立图层下优化重绘)
实验
这是一个消防工程师广告的项目的一个页面,页面布局太简单的话,可能看不出差距
p标签的position属性后定义!
p标签的position 先定义
测试了30次左右,再项目中的css用的较多的情况下(故意多谢一些css,为了让css更多) 用chrome的调试工具的perfomancs项还是有点细微的区别,大体上是:直接表现是css计算时间减少了一点,但是paint时间竟然增加了!!!,