浏览器将 HTML 解析为 DOM,将 CSS 解析为 CSSOM,然后合并 DOM 和 CSSOM 生成 Render Tree。
根据 Render Tree 计算所有节点的大小、位置和样式,最后将节点绘制到页面上。
浏览器使用流式布局,遍历一次 Render Tree 就可以完成页面的绘制,但是 table 元素除外。
Reflow
Reflow 翻译成“回流”不准确,它指的应该是“重新绘制文档流”。
能引起元素周围位置变化的修改都会进行 Reflow,例如修改窗口大小、字体大小以及元素的位置。
会导致 Reflow 的浏览器 API:
clientWidth
,clientHeight
,clientTop
,clientLeft
offsetWidth
,offsetHeight
,offsetTop
,offsetLeft
scrollWidth
,scrollHeight
,scrollTop
,scrollLeft
scrollIntoView()
,scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
Repaint
元素样式的变化不会引起它以及周围元素在文档流中的位置,例如修改背景颜色等操作,浏览器不会 Reflow,只是简单的重新绘制修改的元素,这个叫做 Repaint。
比较
Reflow 代价高于 Repaint,所以尽量避免 Reflow。
CSS 上:
- 避免使用 table 布局,但是用用 table 表格还是可以的
- 尽可能在 DOM 的最末端修改 class,即尽量在子元素上修改样式
- 避免设置多层内联样式
- 动画效果尽量应用在
position
为absolute
或者fixed
的元素上 - 减少 CSS 表达式的使用,例如
calc()
JavaScript 上:
- 不要频繁操作样式,样式应该尽可能一次性修改
- 不要频繁操作 DOM,如有需要,使用 documentFragment
display
为none
的元素不会引发 Reflow 或者 Repaint,可以利用这个特性操作 DOM- 避免频繁读取会引发 Reflow 或者 Repaint 的浏览器 API,如有必要,可以缓存
- 具有复杂动画的元素使用绝对定位,使它脱离文档流,避免周围元素频繁 Reflow
评论区