知识背景
在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和 repaint(重绘) 会大大影响 WEB 性能,尤其是手机页面。因此我们在页面设计的时候要尽量减少 reflow 和 repaint。正确的 CSS 书写顺序不仅方便开放人员进行查看,也不失为优化 CSS 的一种方式
HTML 解析流程
解析 HTML,构建 DOM 树
解析 CSS,生成 CSS 规则树
合并 DOM 树和 CSS 规则,生成 Render 树
布局 Render 树,负责各元素尺寸、位置的计算(reflow 发生在一步)
绘制 Render 树(paint),绘制页面像素信息
浏览器会将各层的信息发送给 GPU,GPU 会将各层合成(composite),显示在屏幕上
回流(reflow)与重绘(repaint)
回流
当 Render 树 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
重绘
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、visibility、background-color 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
回流与重绘的关系
回流必将引起重绘,重绘不一定会引起回流,回流比重绘的代价要更高。
导致重绘 (repaint) 的原因
向元素添加轮廓,更改背景颜色或更改可见性样式
导致回流 (reflow) 的原因
- 改变字体
- 调整窗口大小
- 增加或者移除样式表
- 内容变化,如用户的输入行为
- 激活 CSS 伪类,如 :hover (IE 中为兄弟结点伪类的激活)
- 操作 class 属性
- 脚本操作 DOM
- 计算 offsetWidth 和 offsetHeight 属性
- 设置 style 属性的值
- ...
如何避免回流
- 减少不必要的 DOM 深度。在 DOM 树中的一个级别进行更改可能会致使该树的所有级别(上至根节点,下至所修改节点的子级)都随之变化。这会导致花费更多的时间来执行重排。
- 尽可能减少 CSS 规则的数量,并移除未使用的 CSS 规则。
- 如果您想进行复杂的渲染更改(例如动画),请在流程外执行此操作。您可以使用 position-absolute 或 position-fixed 来实现此目的。
- 避免使用不必要且复杂的 CSS 选择器(尤其是后代选择器),因为此类选择器需要耗用更多的 CPU 处理能力来执行选择器匹配。
CSS 方面
- 避免使用 table 布局。
- 尽可能在 DOM 树的最末端改变 class。
- 避免设置多层内联样式。
- 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。
- 避免使用 CSS 表达式(如:calc())。
JavaScript 方面
- 避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
- 避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
- 也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
CSS 样式的书写顺序
Property Type | Style Sheet |
---|---|
Location | clear,z-index,display,float,overflow,position,top,right,bottom,left |
Itself | margin,padding,width,height,border,background |
Font | font-family,font-size,font-weight,font-varient,color |
Text | text-align,vertical-align,text-wrap,text-transform,text-indent,text-decoration,letter-spacing,word-spacing,white-space,text-overflow |
CSS3 | content,box-shadow,border-radius,transform,transition |