步骤如下
-
根据HTML构建HTML树(DOM树)
-
根据CSS构建CSS树(CSSOM树)
-
将两棵树合并成一颗渲染树(render tree)
-
Layout(回流)布局(文档流、盒模型、计算大小和位置)
-
Painting(重绘)绘制(将边框颜色、文字颜色、阴影等画出来)
-
Compose合成(根据层叠关系展示画面)
有以下三种渲染方式
eg. div.remove()会触发当前消失,其他元素relayout
改变背景颜色,直接repaint+composite
改变transfrom,只需composite
具体可在[ csstriggers.com/ ]查看
何时发生回流重绘
当页面布局和几何信息发生变化的时候,就需要回流。
比如以下情况发生回流:
根据改变的范围和程度,渲染树中或大或小的部分需要重新计算,有些改变会触发整个页面的重排,比如,滚动条出现的时候或者修改了根节点。
- 页面一开始渲染的时候(这肯定避免不了)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 元素字体大小变化
- 激活CSS伪类(例如::hover)
一些常用且会导致回流的属性和方法:
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
以下情况发生重绘而不回流
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程重绘而不回流。
注意:回流一定会触发重绘,而重绘不一定会回流
减少回流和重绘
- 使用 transform 替代 top
- 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)
- 不要把节点的属性值放在一个循环里当成循环里的变量。
- 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
- 动画实现的速度的选择,动画速度越快,回流次数越多,可以使用 requestAnimationFrame
- CSS 选择符从右往左匹配查找,避免节点层级过多
- 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于 video 标签来说,浏览器会自动将该节点变为图层。
动画优化