首先,看一张图片:
首先是解析:
1)这是一个解析的过程,浏览器会解析三个东西:
一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会产生一个DOM Tree。 CSS,解析CSS会产生CSS规则树。 Javascript,脚本,主要是通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree.
2)解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。 CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame。 然后,计算每个Frame(也就是每个Element)的位置,这又叫layout和reflow过程。
3)最后通过调用操作系统Native GUI的API绘制。
其次,就Firefox来说基本上就是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了。
注:Webkit不像Firefox要用两个树来干这个,Webkit也有Style对象,它直接把这个Style对象存在了相应的DOM结点上了。
然后到了,渲染的步骤:
可以把浏览器当成一个画板,它的绘画又包含几个步骤
1 . 计算CSS样式
2 . 构建Render Tree
3 . Layout – 定位坐标和大小,是否换行,各种position, overflow, z-index属性 ……
4 . 正式开画
5 . 完成页面展现.
当然这里还有两个重要的内容,一个是Repaint另一个是Reflow:
- Repaint ——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
- Reflow ——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow)reflow 会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。
那哪些情况会触发这些重绘或重构呢?
1 . 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
2 . 当你移动DOM的位置,或是搞个动画的时候。
3 . 当你修改CSS样式的时候。
4 . 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
5 .当你修改网页的默认字体时。
注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。
最后,Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的。