简析浏览器渲染机制

浏览器渲染流程
1.浏览器解析
(1)浏览器解析HTML,构建DOM树
(2)浏览器解析css,构建CSS规则树
(2)解析JavaScript,通过DOM API和CSSOM API来操作DOM树和 CSS规则树

2.解析完成之后,浏览器将DOM树和CSS规则树构建为渲染树rendering tree
注意:

  • display: none以及header等不会存在在渲染树中
  • CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame
  • 计算每个元素的位置,这又叫reflow或者layout

3.渲染

(1)计算CSS样式
(2)构建Render Tree
(3)Layout – 定位坐标和大小,是否换行,各种position, overflow, z-index属性 ……
(4)通过native GUI paint到页面

关于reflow和repaint

  • Repaint——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
  • Reflow——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow)reflow 会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。

Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的。
所以,下面这些动作有很大可能会是成本比较高的。

  • 当增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当移动DOM的位置,或是搞个动画的时候。
  • 当修改CSS样式的时候。
  • 当Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当修改网页的默认字体时。

为此要尽量减少reflow和repaint
1)不一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。
2)把DOM离线后修改。如:
使用documentFragment 对象在内存里操作DOM
先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。
clone一个DOM结点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
3)不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
4)尽可能的修改层级比较低的DOM。当然,改变层级比较底的DOM有可能会造成大面积的reflow,但是也可能影响范围很小。
5)为动画的HTML元件使用fixed或absolute的position,那么修改他们的CSS是不会reflow的。
6)不使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

本文参考自

陈皓-浏览器的渲染原理简介
Ilya Grigorik-渲染树构建、布局及绘制

推荐阅读更多精彩内容