CSS解释器和样式布局

CSS解释器和规则匹配出于DOM树建立之后,RenderObject树建立之前,CSS解释器解释后的结果会保存起来,然后RenderObject树基于该结果来进行规范匹配和布局计算。

CSS基本功能

CSS全称Cascading Style Sheet,中文名级联样式表,主要用来控制网页的显示风格,其一个比较重要的特征是将网页的内容和内容的展示方式分离。Web开发者有两种方法可以使用CSS,第一种是将CSS代码放入元素“style”中,这称为内部样式表,第二种形如代码< link rel=”stylesheet” type=”text/css” href=”css-url.cc”>这样的用法,引用了一个外部的CSS文档,这称为外部样式表。样式的来源有三种,其一是网页开发者编写的样式信息,它被包含在网页或者外部样式文件中,其二是网页的读者设置的样式信息,读者可以设置一个样式,这个样式可以应用到其游览的网页,其三是游览器的内在默认样式,以上三种类型的优先级是递减的,第一种最为普遍。

样式规则

样式规则是CSS规范中最基本的构成,一个规则包括两个部分-规则头和规则体,规则头由一个或者多个选择器组成,规则体由一个或者多个样式声明组成,每个样式声明由样式名和样式值构成,表示这个规则对哪些样式进行了规定和设置,CSS的样式表示规则如下:
这里写图片描述

选择器

CSS选择器是一组模式,用来匹配相应的HTML元素,当选择器匹配相应元素的时候,该选择器包含的各种样式值就会作用与匹配的元素上,通过选择器,CSS能够准确的控制HTML页面中任意一个或者多个元素的样式属性,从CSS1到CSS3规范陆续加入多达42中选择器,下面介绍其中一些主要的选择器:

  • 标签选择器:根据标签元素的名称来匹配,如上图的的div,它可以选择一个或多个元素
  • 类型选择器: 根据类型信息来选择目标元素,类型选择器可以选择一个或多个元素,上图div元素也可以使用类型选择器,方法是“.aclass”
  • ID选择器: 根据元素ID来选择目标元素,一个选择器仅能选择一个元素,这是因为ID的唯一性,上图div元素也可以使用ID选择器,方法是“#adiv”
  • 属性选择器: 根据属性来选择目标元素,可以选择一个或多个,上图div可以使用属性选择器,方法是”div[i]”, “div[id=’adiv’]”, “div[id~=’di’]”, “id|=’ad’”
  • 后台选择器:选择某元素包含的后代元素,可以选择一个或者多个,上图div可以选择使用后代选择器,“body div”
  • 子女选择器: 选择某元素包含的子女元素,可以选择一个或者多个,上图div可以选择使用,“body>div”
  • 相邻同胞选择器: 根据相邻同胞信息来确定选择的元素,可以选择一个或者多个,上图div可以选择使用,“p+div”

选择器存在优先级的问题,一般而言,选择器描述的越具体,它的优先级越高,也就是说选择器指向的越准确,它的优先级就越高。标准中引入了两个新的JavaScript接口:QuerySelector和QuerySelectorAll,这两个接口让CSS定义的所有选择器都可以作为参数传给这两个接口,从而获取到相应的HTML页面中的DOM节点。

框模型

框模型是CSS标准中引入来表示HTML标签元素的布局结构,一个框模型大致包括四个部分,它们从外到内分别是外边据,边框,内边距和内容,在HTML网页中,每个可视元素的布局都是按照框模型来设计的,网页通过对元素设置这些样式属性,就可以达到特定的布局效果。
这里写图片描述

包含块模型

当WebKit计算元素的箱子的位置和大小时,WebKit需要计算该元素和另外一个矩形区域的相对位置,这个矩形区域称为该元素的包含块,框模型就是在包含块内计算和确定各个元素的,具体定义如下:

  • 根元素的包含块称为初始包含块,通常它的大小是可视区域(Viewport)的大小
  • 对于其他位置属性设置为“static”或者“relative”的元素,它的包含块就是最近祖先的箱子模型的内容区域(Content)
  • 如果元素的位置属性设置为“fixed”,那么该元素的包含块脱离HTML文档,固定在可视区域的某个特定位置
  • 如果元素的位置属性为“absolute”,那么该元素的包含块由最近的含有属性“absolute”,“relative”或者“fixed”的祖先决定,具体规则如下:如果一个元素具有“inline”属性,那么该元素的包含块是包含该祖先的第一个和最后一个inline框的内边距的区域
CSS样式属性

CSS标准中定义了各式各样的样式属性,用来描述元素的显示效果,属性大致可以分为一下几类:

  • 背景:通常有两种方式来显示背景,一种是设置背景颜色(background-color),另一种是设备背景图片
  • 文本:设置文本缩进、对其、单词间隔、字母间隔、字符换行、装饰和空白字符等
  • 字体:设置字体属性,可以是内嵌的,也定义是自定义字体的方式,另外还可以设置加粗、变形等属性
  • 列表:设置列表类型,可以以字母、希腊字母、数字等方式编号列表
  • 表格:通过设置边框来达到显示表格的视觉效果,设置是否把表格边框合并为单一的边框,设置分隔单元格边框的距离,设置表格标题的位置,设置是否显示表格中的空单元格,设置显示单元、行和列的算法等
  • 定义:CSS提供元素的相对、绝对定位和浮动定位
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接口进行了扩展,下面是新加入的属性:

partial interface Document{
   readonly attribute StyleSheetList styleSheets;
   attribute DOMString? selectedStyleSheetSet;
   readonly attribute DOMString? lastStyleSheetSet;
   readonly attribute DOMString? preferredStyleSheetSet;
   readonly attribute DOMString[] styleSheetSets;
   void enableStyleSheetsForSet(DOMString? name);
};

通过上面这些属性,开发者可以动态选择使用哪些CSS样式表,获取的样式表就是前面定义的CSSStyleSheet对象,JavaScript代码可以修改这些对象的属性。W3C还定义了另外一个规范,就是CSSOM View,它的基本含义是增加一些新的属性到Window,Document,Element,HTMLElement和MouseEvent等接口,这些CSS的属性能够让JavaScript获取属兔信息,用于表示跟试图相关的特征,例如窗口大小,网页滚动位移,元素的框位置,鼠标事件的坐标等信息,这些特征在很多游览器中获得了支持,以下以Window的扩展为例:

partial interface Window {
   MediaQueryList matchMedia(DOMString media_query_list);
   readonly attribute Screen screen;
   // viewport
   readonly attribute long innerWidth;
   readonly attribute long innerHeight;
   // viewport scrolling
   readonly attribute long scrollX;
   readonly attribute long pageXOffset;
   readonly attribute long scrollY;
   readonly attribute long pageYOffset;
};
CSS解释器和规则匹配

在DOM树中,CSS样式可以包含在“style”元素中或者使用“link”来引用一个CSS文档,对于CSS样式表,不管是内嵌还是外部文档,WebKit都使用CSSStyleSheet类来表示,下图描述了WebKit内部是如何表示CSS文档的:

这里写图片描述

DOM中Document类是起始类,它包括一个DocumentStypeSheetCollection类,该类包含了所有CSS样式表,还包括webkit的内部表示类CSSStyleSheet,它包含CSS的hef、类型、内容等信息,CSS的内容就是样式信息StyleSheetContents,包含了一个样式规则(StyleRuleBase)列表,样式规则被用在CSS的解释器的工作过程中。下面部分的webkit主要是将解释之后的规则组织起来,用于为DOM中的元素匹配相应的规则,从而应用规则中的属性值序列,这一过程的主要负责者是StyleSheetResolver类,它属于Document类,并包含一个DocumentRuleSets类用来表示多个规则集合,每个规则集合都是将之前解释之后的结果合并起来并进行分类。样式规则是解释器的输出结构,是样式匹配的输入数据,样式规则有很多类型,具体包含如下:

  • Style:基本类型,大多数规则属于这个类型
  • Import:是WebKit中为了方便而引入的,其对应的是一个导入CSS文件的Style元素
  • Media:对应于CSS标准中的@media类型
  • Fontface:CSS3新引入的自定义字体的规则类型
  • Page:对应与CSS标准中的@page类型
  • Keyframes:对应与WebKit中的@-webkit-key-frames类型,可以用来定制特定帧的样式属性信息
  • Region:对CSS标准正在进行中的Regions的支持,这方便了开发者对页面进行分区域排版

类及相关继承关系:
这里写图片描述

解释过程

CSS解释过程是指从CSS字符串进过CSS解释器处理后变成渲染引擎的内部规则表示的过程,在webkit中,表示过程如下:
这里写图片描述
其基本思想由CSSParser类负责,CSSParser类属于桥接类,实际解释工作由CSSGrammer.y.in来完成,CSSGrammer.y.in是Bison的输入文件,Bison是一个生成解释器的工具,Bison根据CSSGrammer.y.in生成CSS解释器-CSSGrammer类,CSSGrammer类需要调用CSSParser类来处理解释结果,例如使用CSSParser类创建选择器对象、属性、规则等。

样式规则匹配

样式规则建立完成之后,WebKit保存规则结果在DocumentRuleSets对象类中,当DOM的节点建立之后,WebKit会为其中的一些节点选择合适的样式信息,这些工作由StyleResolver来负责,实际的匹配工作在DocumentRuleSets类中完成。样式规则匹配WebKit主要相关类如下:
这里写图片描述
主要思想是使用StyleResolver类来为DOM的元素节点匹配样式,StyleResolver类根据元素的信息,例如标签名,类别等,从样式规则中查找最匹配的规则,然后将样式信息保存到新建的RenderStyle对象中,最后这些RenderStyle对象被RenderObject类所管理和使用。

WebKit布局
基础

WebKit创建RenderObject对象之后,每个对象不知道自己的位置、大小等信息,WebKit根据框模型来计算它们的位置、大小等信息的过程称为布局计算。Frame类用于表示网页的框结构,每个框都有FrameView类,用于表示框的视图结构,FrameView类主要负责试图方面的任务,包括网页视图大小,滚动,布局计算,绘图等,它是一个总入口类。布局计算根据其计算的范围大致可以分为两类:第一类是对整个RenderObject树进行计算,第二类是对RenderObject树中某个子树的计算,常见与文本元素或overflow:auto块的计算,这种情况一般是其子树布局的改变不会影响其周围元素的布局,因为不需要重新计算更大范围内的布局。

布局计算

布局计算是一个递归的过程,因为一个节点的大小通常需要先计算它的子女的位置,大小等信息。布局的主要逻辑由RenderObject类的“layout”函数来完成,首先,该函数会判断RenderObject节点是否需要重新计算,通常这需要通过检查位数组中的相应标记为、子女是否需要计算布局等来确定;其次,该函数会确定网页的宽度和垂直方向上的外边距,因为网页通常是在垂直向上滚动,而水平方向尽量不需要滚动;再次该函数会遍历其每一个子女节点,依次计算它们的布局,每一个元素会实现自己的“layout”函数,根据特定的算法来计算该类型元素的布局,如果页面元素定义了自身的宽高,那么WebKit按照定义的宽高来确定元素的大小,而对于像文本节点这样的内联元素则需要结合其字号大小及文字的多少等来确定其对应的宽高,如果页面元素所确定的宽高超过了布局容器包含块所能提供的宽高,同时其overflow的属性为visible或auto,WebKit则会提供滚动条来保证可以显示其所有的内容,除非网页定义了页面元素的宽高,一般页面元素的宽高是在布局的时候通过相关计算得出来的,如果元素存在子女,则WebKit需要递归这一过程;最后,节点根据它的子女的大小计算得出自己的高度,整个过程结束。

布局计算过程如下:
这里写图片描述

对于以下几种情况会触发重新布局:
① 当网页首次被打开的时候,游览器设置网页的可视区域,并调用计算布局的方法;
② 网页的动画会触发布局计算,因为动画可能改变样式属性;
③ JavaScript代码通过CSSOM等直接修改样式信息;
④ 用户的交互,例如翻滚网页等;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值