前言
此文章是我最近在看的【WebKit 技术内幕】一书的一些理解和做的笔记。
而【WebKit 技术内幕】是基于 WebKit 的 Chromium 项目的讲解。
本文剖析 WebKit 的 CSS 解释器和样式布局。
从整个网页的加载和渲染过程来看,CSS 解释器和规则匹配处于 DOM 树建立之后,RenderObject 树建立之前,CSS 解释器解释后的结果会保存起来,然后 RenderObject 树基于该结果来进行规范匹配和布局计算。当网页有用户交互或者动画等动作的时候,通过 CSSDOM 等技术,JavaScript 代码同样可以非常方便地修改 CSS 代码,WebKit 此时需要重新解释样式并重复以上这一过程。
1. CSS 基本功能
1.1.1 简介
CSS 的全称是 Cascading Style Sheet,中文名是级联样式表,主要用来控制网页的显示风格。
1.1.2 样式规则
图 6-1 描述了一个典型的 CSS 规则结构。一个规则包括两个部分——规则关和规则体。规则头由一个或者多个选择器组成;规则体则由一个或者多个样式声明组成,每个样式声明由样式名和样式值构成,表示这个规则对哪些样式进行了规定和设置。
当 HTML 中的某个元素经过后面的匹配算法使用了这条规则,那么将这些样式设置成该元素的样式,除非有更高优先级的规则匹配上该元素。
1.1.3 选择器
CSS 的选择器是一级模式,用来匹配相应的 HTML 元素。当选择器匹配相应元素的时候,该选择器包含的各种样式值就会作用于匹配的元素上。通过选择器,CSS 能够精准地控制 HTML 页面中的任意一个或者多个元素的样式属性。
具体的,这里不做介绍,请查阅 CSS 规范。
1.1.4 框模型
框模型(Box model,或称箱子模型)就是我们常说的盒子模型,是CSS 标准中引入来表示 HTML 标签元素的布局结构。一个框模型大致包括四个部分:外边距(Margin)、边框(Border)、内边距(Padding)和内容(Content)。
1.4.5 包含块(Containing Block)模型
当 WebKit 计算元素的箱子的位置和大小时,WebKit 需要计算该元素和另外一个矩形区域的相对位置,这个矩形区域称为该元素的包含块。上面介绍的框模型就是在包含块内计算和确定各个元素的,包含块的具体定义如下:
- 根元素的包含块称为初始包含块,通常它的大小就是可视区域(Viewport)的大小。
- 对于其他位置属性设置为 “static” 或者 “relative” 的元素,它的包含块就是最近祖先的箱子模型中的内容区域(Content)。
- 如果元素的位置属性为 “fixed” ,那么该元素的包含快脱离 HTML 文档,因定在可视区域的某个特定位置。
- 如果元素的位置属性为 “absolute” ,那么该元素的包含块由最近的含有属性 “absolute”、“relative”、或者 “fixed” 的祖先决定,具体规则如下:如果一个元素具有 “inline” 属性,那么元素的包含块是该祖先的第一个和最近一个 inline 框的内边距的区域;否则,包含块则是该祖先的内边距所包围的区域。
1.1.6 CSS 样式属性
CSS 标准中定义了各式各样的样式属性,用来描述元素的显示效果。
这些属性大致分成以下类型:
- 背景:如背景颜色和背景图片等。
- 文本:设置文本缩进,对齐。单词间隔。字母间隔。字符转换、装饰和空白字符等。
- 字体:设置字体属性,可以是内嵌的,也可以是自定义字体的方式,另外还可以设置加粗、变形等属性。
- 列表:设置列表类型,可以以字母、希腊字母、数字等方式编号列表。
- 表格:通过设置边框来达到显示表格的视觉效果的目的。设置是否把表格边框合并为单一的边框,设置分隔单元格边框的距离,设置表格标题的位置,设置是否显示表格中的空单元格,设置显示单元、行和列的算法等。
- 定位:CSS 提供元素的相对、绝对定位和浮动定位。
1.1.7 CSSOM(CSS Object Model)
CSSOM 称为 CSS 对象模型。它思想是在 DOM 中的一些节点接口中,加入获取和操作 CSS 属性或者接口的 JavaScript 接口,因而 JavaScript 可以动态操作 CSS 样式。DOM 提供了接口让 JavaScript 修改 HTML 文档,同理,CSSOM 提供了接口让 JavaScript 获得和修改 CSS 代码设置的样式信息。
对于内部和外部样式表,CSSOM 定义了样式表的接口,称为 “CSSStyleSheet”, 这是一个可以在 JavaScript 代码中访问的接口。借助这个接口,开发者可以在 JavaScript 中获取样式表的各种信息,例如 CSS 的 “href”、样式表类型 “type”、规则信息 “cssRules” 等,甚至可以获取样式表中的 CSS 规则列表。这个接口同 DOM 中的 “Script” 节点或者 “Link” 节点不一样,它是 CSSOM 定义的新接口。开发者可以通过 document.styleSheets 查看当前网页中包含的所有 CSS 样式表,这是因为 CSSOM 对 DOM 中的 Document 接口进行了扩展,下面是新加入的属性:
W3C 还定义了另外一个规范是 CSSDOM View,它的基本含义是增加一些新的属性到 Window、Document、Element、HTMLElement 和 MouseEvent 等接口,这些 CSS 的属性能够让 JavaScript 获取视图信息,用于表示跟视图相关的特征,例如窗口大小,网页滚动位移,元素的框位置、鼠标事件的坐标等信息。下面是以 CSSDOM View 对 Window 的扩展: