William's Blog

现代浏览器的工作原理(三)

解析CSS的流程

  现代浏览器解析CSS文档的流程如图1所示。

图 1 现代浏览器解析CSS的流程

  现代浏览器解析CSS的流程与解析html的流程类似:从网络或者本地获取CSS文件后,经过解码器、预处理器、标记生成器以及树构建器处理之后生成一个CSSStyleSheet对象。解析流程中的关键处理步骤说明如下:
  (1)Byte Stream Decoder(字节流解码器):将获取到的CSS字节流解析成Unicode编码表示的字符流。关于更多解码细节,可以查看CSS3标准
  (2)Input Stream Preprocessor(输入字符流预处理器):对解码产生的Unicode字符流进行预处理。主要进行如下两个操作:1、将所有的单个 “回车(CR)” 字符、“翻页(FF)” 字符以及 “回车换行(CRLF)” 字符对替换成单个 “换行(LF)” 字符。2、将所有的 “空(U+0000 NULL)” 字符替换成 “替换(U+FFFD REPLACEMENT CHARACTER)” 字符。
  (3)Tokenizer(标记生成器):处理步骤(2)生成的字符流,生成CSS标记并将标记传送给树生成器。CSS标记有多种,如标识符标记(<ident-token>)、@标记(<at-keyword-token>)、数字标记(<number-token>)。CSS3标准给出了CSS标记的具体定义,可以查看CSS3标准来获得每个CSS标记的具体定义。标记生成器的标记化算法可以用状态机来表示,具体的算法实现流程可以参阅CSS3标准
  (4)Tree Construction(树构建):根据标记生成器产生的一系列CSS标记,构建CSSOM树,树的根节点是CSSStyleSheet对象。CSSStyleSheet对象包含CSSRule对象,CSSRule对象又包含Selectors对象和Declaration对象以及其他与CSS语法对应的对象。

解析CSS示例

  按照上述现代浏览器解析CSS文档的流程,以下CSS片段被解析之后生成的CSSOM树如图2所示。

div {
    background: blue;
}

div p {
   font-size: 16px;
}
图 2 CSS解析示例

构建呈现树

  浏览器在解析构架DOM树的同时,还会构建呈现树。呈现树是由可视化元素按照其显示顺序组成的树,是文档的可视化表示。Firefox将呈现器中的元素称为 “框架(frame)“,Webkit将其称之为 “呈现器(renderer)” 或者 “呈现对象(render object)“。
  呈现器(呈现对象)知道如何布局以及将自身及其子元素绘制出来。每一个呈现器都代表了一个矩形区域,通常对应于相关节点的CSS框,包含诸如宽度、高度、位置等几何信息。节点CSS样式中display属性的不同,浏览器创建出的呈现器的类型也不同,如inline和block。浏览器创建呈现器时也会考虑元素类型,有些特殊的元素类型对应特殊的呈现器(框架),如表单。

呈现树和DOM树的关系

  呈现树与DOM树相对应,但并不是一一对应的。非可视化(注:不包括visibility属性值为hidden的元素)的元素(如head元素、display属性为none的元素)不会被插入到呈现树中。
  对于一些具有复杂结构的元素,其无法用单一的矩形来描述,浏览器会为这些元素创建多个可视化对象。如select元素有3个呈现器:一个用于显示区域,一个用于下拉列表框,还有一个用于按钮。一个Text节点也可能对应多个可视化对象,如当宽度不够时,文本无法在一行中显示而分为多行,那么新的行也会作为新的呈现器而添加。
  还有一些呈现对象在呈现树中所处的位置与DOM节点在DOM树中所处的位置并不对应。对于设置了浮动和定位的元素就会出现这种情况,这些元素处于文档的正常流程之外,其对应的呈现对象放置在呈现树的其他地方并映射到真正的呈现器(框架),放在原位的是占位框架。
  图3显示了DOM树与呈现树的对应关系(查看原文

图 3 DOM树与呈现树的对应关系
  在DOM树构建的过程中,浏览器遇到html或者body标记就会创建呈现树的根节点。这个根节点呈现对象对应于CSS的容器block,该block包含了所有其他的block,是最上层的block。这个block的尺寸就是浏览器的视口大小,Firefox称之为ViewPortFrame,Webkit称之为RenderView。呈现树的其余部分将会以DOM树节点插入的形式来创建。

参考文献

  1. html5rocks: How Browsers Work: Behind the scenes of modern web browsers
  2. HTML: The HTML syntax

William

本博客作者 William 现任职于北京贝壳找房,从事web前端开发相关工作。
您可以通过Email与他取得联系