css优化之重排与重绘
浏览器的渲染机制
主要分为以下几个步骤:
- 解析HTML(HTML Parser)
- 构建DOM树(DOM Tree)
- 渲染树构建(Render Tree)
- 绘制渲染树(Painting)
浏览器取回代码后,首先会构造DOM树,根据HTML标签,构造DOM树。
之后会解析CSS样式,解析的顺序是浏览器的样式
-> 用户自定义的样式
-> 页面的link标签等引进来的样式
-> 写在style标签里面的内联样式
网页生成的时候,至少会渲染一次。用户访问的过程中,还会不断重新渲染。
重新渲染,就需要重新生成布局和重新绘制。前者叫做重排(reflow),后者叫做重绘(repaint)。
需要注意的是,重绘不一定需要重排,重排必然导致重绘。
为了提高网页性能,就要降低"重排"和"重绘"的频率和成本,尽量少触发重新渲染。
慎重选择高消耗的样式
什么 CSS 属性是高消耗的?就是那些绘制前需要浏览器进行大量计算的属性。
-
box-shadows
-
border-radius
-
transparency
-
transforms
-
CSS filters(性能杀手)
什么是reflow
浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构的进程叫做reflow
.
通俗点说就是当开发人员定义好了样式后(也包括浏览器的默认样式),浏览器根据这些来计算并根据结果将元素放到它应该出现的位置上,这个过程叫做reflow
.
由于reflow
是一种浏览器中的用户拦截操作,所以我们了解如何减少reflow次数,及DOM的层级,css效率对refolw次数的影响是十分有必要的。
reflow(回流)是导致DOM脚本执行效率低的关键因素之一,页面上任何一个节点触发了reflow,会导致它的子节点及祖先节点重新渲染。
<body> <div class="hello"> <h4>hello</h4> <p><strong>Name:</strong>BDing</p> <h5>male</h5> <ol> <li>coding</li> <li>loving</li> </ol> </div> </body>
当p节点上发生reflow时,hello和body也会重新渲染,甚至h5和ol都会收到影响。
什么时候会导致reflow发生呢?
- 改变窗口大小
- 改变文字大小
- 添加/删除样式表
- 内容的改变,(用户在输入框中写入内容也会)
- 激活伪类,如:hover
- 操作class属性
- 脚本操作DOM
- 计算offsetWidth和offsetHeight
- 设置style属性
常见的重排元素 | ||||
---|---|---|---|---|
width | height | padding | margin | |
display | border-width | border | top | |
position | font-size | float | text-align | |
overflow-y | font-weight | overflow | left | |
font-family | line-height | vertical-align | right | |
clear | white-space | bottom | min-height |
怎么减少 Reflow
-
不要一条一条地修改 DOM 的样式,预先定义好 class,然后修改 DOM 的
className
-
把 DOM 离线后修改,比如:先把 DOM 给
display:none
(有一次 Reflow),然后你修改100次,然后再把它显示出来 -
不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
-
尽可能不要修改影响范围比较大的 DOM
-
为动画的元素使用绝对定位
absolute / fixed
-
不要使用
table
布局,可能很小的一个小改动会造成整个 table 的重新布局
什么是repaint
repaint是在一个元素的外观被改变,但没有改变布局的情况下发生的,如改变了visibility、outline、background等。当repaint发生时,浏览器会验证DOM树上所有其他节点的visibility属性。·
通俗来说,就是当各种盒子的位置、大小以及其他属性,例如颜色、字体都确定下来后,浏览器便把这些元素都按照各自的特性绘制一遍,于是页面的内容出现了,这个过程叫做repaint
避免过分重绘(Repaints)
当元素改变的时候,将不会影响元素在页面当中的位置(比如 background-color
, border-color
, visibility
),浏览器仅仅会应用新的样式重绘此元素,此过程称为 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 |
优化动画
css3 动画是优化的重中之重。除了做到上面两点,减少 Reflow 和 Repaints
之外,还需要注意以下方面。
启用 GPU 硬件加速
GPU
(Graphics Processing Unit) 是图像处理器
。GPU
硬件加速是指应用 GPU
的图形性能对浏览器中的一些图形操作交给 GPU
来完成,因为 GPU
是专门为处理图形而设计
,所以它在速度和能耗
上更有效率。
GPU
加速可以不仅应用于3D,而且也可以应用于2D。这里, GPU
加速通常包括以下几个部分:Canvas2D
,布局合成(Layout Compositing)
, CSS3转换(transitions)
,CSS3 3D变换(transforms)
,WebGL
和视频(video)
。
/* * 根据上面的结论 * 将 2d transform 换成 3d * 就可以强制开启 GPU 加速 * 提高动画性能 */ div { transform: translate(10px, 10px); } div { transform: translate3d(10px, 10px, 0); }
需要注意的是,开启硬件加速相应的也会有额外的开销,参见这篇文章 CSS 硬件加速的好与坏·
参考以下文章: