《WebKit 技术内幕》学习之六(2): CSS解释器和样式布局

2 CSS解释器和规则匹配

        在了解了CSS的基本概念之后,下面来理解WebKit如何来解释CSS代码并选择相应的规则。通过介绍WebKit的主要设施帮助理解WebKit的内部工作原理和机制。

2.1 样式的WebKit表示类

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

                                         图CSS的内部结构主要类和关系

        一切的起源都是从DOM中的Document类开始。先看Document类之外的左上部分:包括一个DocumentStyleSheetCollection类,该类包含了所有CSS样式表;还包括WebKit的内部表示类CSSStyleSheet,它包含CSS的href、类型、内容等信息。CSS的内容就是样式信息StyleSheetContents,包含了一个样式规则(StyleRuleBase)列表。样式规则被用在CSS的解释器的工作过程中。

        下面的部分WebKit主要是将解释之后的规则组织起来,用于为DOM中的元素匹配相应的规则,从而应用规则中的属性值序列。这一过程的主要负责者是StyleSheetResolver类,它属于Document类,并包含了一个DocumentRuleSets类用来表示多个规则集合(RuleSet)。每个规则集合都是将之前解释之后的结果合并起来,并进行分类,例如id类规则、标签类规则等。至于为什么是多个规则集合,是因为这些规则集合可能源自于默认的规则集合(前面提到过WebKit使用默认的CSS样式信息),或者网页自定义的规则集合等。

        下面让我们更进一步重点介绍样式规则。样式规则是解释器的输出结构,是样式匹配的输入数据。样式规则有很多类型,图描述了这些类和继承关系。

                                图StyleRuleBase和它的子类们

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

        这些类基本上跟CSS的标准相对应,当然也有特例,那就是StyleRuleImport,它是WebKit引入的一个新的类型,主要对应的是导入CSS文件的元素。

        接下来剖析规则的内部是如何组成和表示的。图描述的是一个CSS规则(从示例代码中获取)和WebKit的内部结构表示类。

                                图CSS样式规则和WebKit的内部结构表示类

        首先最外层的是样式规则,通常一个样式表可能包括一个或者多个样式规则,这里描述的样式规则对应于图中的StyleRule类。

        然后是选择器部分,图的上半部分是一个选择器列表,这在现实中是比较常见的,因为选择的条件可能有多个。举个例子,“a[class=abc]”其实是两个选择器合起来的,第一个是“a”,它是一个标签选择器;第二个是“[class=abc]”,它是一个属性选择器。这两个选择器合起来的含义就是匹配元素是“a”的标签并且它的类别为“abc”。选择器在WebKit的内部表示是CSSSelector类。在规则中,CSSSelector类使用一个对象列表来表示它们。

        最后是这个规则对应的属性集合CSSPropertySet。WebKit使用了一些类来分别表示属性名字CSSPropertyID (1) 、属性值CSSValue。图6-7清晰地描述了它们的结构。

2.2 解释过程

        CSS解释过程是指从CSS字符串经过CSS解释器处理后变成渲染引擎的内部规则表示的过程。在WebKit中,这一过程如图所示。

                                图CSS解释器的工作过程

        这一过程并不复杂,基本的思想是由CSSParser类负责。CSSParser类其实也是桥接类,实际的解释工作是由CSSGrammer.y.in来完成。CSSGrammer.y.in是Bison的输入文件,Bison是一个生成解释器的工具。Bison根据CSSGrammer.y.in生成CSS解释器——CSSGrammer类。当然CSSGrammer类需要调用CSSParser类来处理解释结果,例如需要使用CSSParser类创建选择器对象、属性、规则等。

        图描述的正是这一过程。当WebKit需要解释CSS内容的时候,它调用CSSParser对象来设置CSSGrammer对象等,解释过程中需要的回调函数由CSSParser来负责处理,最后WebKit将创建好的结果直接设置到StyleSheetContents对象中,这一过程显得直接而且简单。

        在解释网页中自定义的CSS样式之前,实际上WebKit渲染引擎会为每个网页设置一个默认的样式,这决定了网页所没有设置的元素属性及其属性默认值和将要显示的效果。一般来讲,不同的WebKit移植可以设置不同的默认样式。下面是Chrome浏览器使用的默认样式,这些样式决定了默认的网页显示效果。

"html,body,div{display:block}head{display:none}body{margin:8px}div:focus, span:focus{outline:auto 5px-webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"

2.3 样式规则匹配

        样式规则建立完成之后,WebKit保存规则结果在DocumentRuleSets对象类中。当DOM的节点建立之后,WebKit会为其中的一些节点(只限于可视节点,在第7章中介绍)选择合适的样式信息。根据前面的描述,这些工作都是由StyleResolver来负责的。当然,实际的匹配工作还是在DocumentRuleSets类中完成的。

        图描述了参与样式规则匹配的WebKit主要相关类。基本的思路是使用StyleResolver类来为DOM的元素节点匹配样式。StyleResolver类根据元素的信息,例如标签名、类别等,从样式规则中查找最匹配的规则,然后将样式信息保存到新建的RenderStyle对象中。最后,这些RenderStyle对象被RenderObject类所管理和使用。

                                图CSS样式规则匹配使用的主要WebKit类

        规则的匹配则是由ElementRuleCollector类来计算并获得,它根据元素的属性等信息,并从DocumentRuleSets类中获取规则集合,依次按照ID、类别、标签等选择器信息逐次匹配获得元素的样式。那么具体的过程如何呢?图为我们描述了WebKit如何为HTML元素获取样式并从规则集合中匹配的过程。

                        图为HTML元素获取样式和WebKit的样式规则匹配过程

        首先,当WebKit需要为HTML元素创建RenderObject类的时候,首先StyleResolver类负责获取样式信息,并返回RenderStyle对象,RenderStyle对象包含了匹配完的结果样式信息。

        其次,根据实际需求,每个元素可能需要匹配不同来源的规则,依次是用户代理(浏览器)规则集合、用户规则集合和HTML网页中包含的自定义规则集合。这三个规则的匹配方式是类似的,这里是以自定义规则的匹配为例加以说明的。

        再次,对于自定义规则集合,它先查找ID规则,检查有无匹配的规则,之后依次检查类型规则、标签规则等。如果某个规则匹配上该元素,WebKit把这些规则保存到匹配结果中。

        最后,WebKit对这些规则进行排序。对于该元素需要的样式属性,WebKit选择从高优先级规则中选取,并将样式属性值返回。

2.4 实践:样式匹配

为了理解样式的实际匹配过程和结果,以网页“http://lab.hakim.se/reveal-js/”为例,详细的步骤如下。

        首先,打开Chrome浏览器输入上述网页地址,并打开开发者工具,单击“Elements”按钮。

        其次,在开发者工具中单击“打开网页的源代码”按钮,选择“body”元素,在开发者工具的右侧,读者会看到如图6-11左边部分所示经过计算的该元素的匹配结果样式(Computed Style)。用户甚至可以直接在开发者工具中修改属性值,看看它们是如何影响布局的。

                                        图网页的样式计算和规则匹配

               最后,查看一下“styles”中的“Matched CSS Rules”,这些规则能够匹配上该节点的规则列表,但是不同的属性可能来源于不同的规则。在本例中,读者可以看到图中右边的部分就是当前匹配上的各个样式规则,它们来源于不同的CSS样式表中不同的规则。前面四个规则来源于网页自定义的样式表,最后一个“user agent stylesheet”来源于浏览器默认样式表。这些规则中有些对属性的设置有冲突,当然规则按照CSS标准定义的优先级来选择。图中被线划掉的表示该属性没有对当前元素起作用,这包含了两种情形:第一是属性设置错误;第二是被更高优先级的规则属性覆盖。开发者通过元素的具体匹配规则可以调试和修改自己的样式规则。

2.5 JavaScript设置样式

        CSSOM定义了JavaScript访问样式的能力和方式。示例代码6-1中的第29行所示的是使用CSSOM接口来更改属性值的。在WebKit中,这需要JavaScript引擎和渲染引擎协同完成。为了描述这一过程,可能会涉及到一些JavaScript引擎的调用,目前比较难以理解,所以读者只需要有一个大致的印象即可,在第9章的JavaScript引擎中会有更详细和系统的介绍。

        大致的过程是,JavaScript引擎调用设置属性值的公共处理函数,然后该函数调用属性值解析函数,在这个例子中则是CSS的JavaScript绑定函数。而后WebKit将解析后的信息设置到元素的“style”属性的样式“webkitTransform”中,然后设置标记表明该元素需要重新计算样式,并触发重新计算布局。最后就是WebKit的重新绘图,图6-12描述了其中的主要过程。

                                       图WebKit引擎和JavaScript引擎设置样式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/643155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity刷新grid,列表

获取UIGrid 组件,更新列表 listParent.GetComponent().repositionNow true;

自然语言处理--概率最大中文分词

自然语言处理附加作业--概率最大中文分词 一、理论描述 中文分词是指将中文句子或文本按照语义和语法规则进行切分成词语的过程。在中文语言中,词语之间没有明显的空格或标点符号来分隔,因此需要通过分词工具或算法来实现对中文文本的分词处理。分词的…

[C++]使用yolov8的onnx模型仅用opencv和bytetrack实现目标追踪

【官方框架地址】 yolov8: https://github.com/ultralytics/ultralytics bytetrack: https://github.com/ifzhang/ByteTrack 【算法介绍】 随着人工智能技术的不断发展,目标追踪已成为计算机视觉领域的重要研究方向。Yolov8和ByTetrack作为当前先进的算法&…

Python实现两因素独立设计方差分析,简单效应分析

# Python实现两因素独立设计方差分析 1. 背景 1. 有研究者探讨了在不同企业文化下,管理者的不同语言风格所产生的影响 有的企业注重员工的独立性,强调个人努力和内部竞争;有的企业注重员工的整体性,强调团队合作和团队绩效。 …

LCD液晶屏驱动详解(3)

2.2、LCD控制寄存器LCDCON2 用于设置垂直方向各信号的时间参数,格式如下表所示: 功能位说明VBPD[31:24]VSYNC信号脉冲之后,还要经过(VBPD1)个HSYNC信号周期,有效的行数据才出现;LINEVAL[23:14]LCD的垂直宽度&#xf…

2024PMP考试新考纲-【过程领域】近期典型真题和很详细解析(11)

华研荟继续为您分享【过程Process领域】的新考纲下的真题,帮助大家体会和理解新考纲下PMP的考试特点和如何应用所学的知识和常识(经验)来解题,并且举一反三,一次性3A通过2024年PMP考试。 2024年PMP考试新考纲-【过程领…

探索文件与交互:使用PyQt5构建一个高级文件选择器

在当今的应用程序开发中,文件管理和交互是一个重要的组成部分。特别是对于桌面应用程序,提供一个直观、功能丰富的文件选择器是提高用户体验的关键。 本篇博客,我将介绍如何使用Python和PyQt5来构建一个高级的文件选择器,它不仅能…

数据挖掘笔记1

课程:清华大学-数据挖掘:理论与算法(国家级精品课)_哔哩哔哩_bilibili 一、Learning Resources 二、Data 数据是最底层的一种表现形式。数据具有连续性。从存储上来讲,数据分为逻辑上的和物理层的。大数据&#xff1…

np.bincount函数的用法

官网写的非常清晰了, 返回数组的数量比x中的最大值大1,它给出了每个索引值在x中出现的次数。下面,我举个例子让大家更好的理解一下: np.bincount(np.array([0, 1, 1, 3, 2, 1, 7])) array([1, 3, 1, 1, 0, 0, 0, 1])最大值是7&a…

BUU BRUTE 1

靶场教程 1.开局页面,是个登录界面。2.尝试万能密码,发现并不可行,提示【用户名错误】。用户名输入admin,发现提示密码错误,为四位数字。3.那么,抓包爆破吧。通过burp进行抓包。4.发送包到 Intruder 进行爆…

Redis(七)复制

文章目录 是什么功能配置配主库不配从库权限细节 案例配置文件修改 一主二仆固定配置文件主从问题命令操作手动指定 薪火相传反客为主复制原理和工作流程存在问题 是什么 https://redis.io/docs/management/replication/ 就是主从复制,master以写为主,S…

Ubuntu findfont: Font family ‘SimHei‘ not found.

matplotlib中文乱码显示 当我们遇到这样奇怪的问题时, 结果往往很搞笑 尝试1不行 Stopping Jupyter Installing font-manager: sudo apt install font-manager Cleaning the matplotlib cache directory: rm ~/.cache/matplotlib -fr Restarting Jupyter. 尝试2 This work fo…

Kafka-服务端-副本机制

Kafka从0.8版本开始引入副本(Replica)的机制,其目的是为了增加Kafka集群的高可用性。 Kafka实现副本机制之后,每个分区可以有多个副本,并且会从其副本集合(Assigned Replica,AR)中选出一个副本作为Leader副本,所有的读写请求都由…

Bluetooth Device Address(BD_ADDR) - 2

蓝牙核心规范:Core v5.3中关于蓝牙地址的其他说明 Vol 3: Host, Part C: Generic Access Profile 3 User interface aspects 3.2 Representation of Bluetooth parameters 3.2.1 Bluetooth Device Address (BD_ADDR) BD_ADDR 是蓝牙设备使用的地址。在设备发现过…

IPoE技术汇总

在国内并没有遇到这么多的IPoE(IP over Ethernet)技术,可能也是因为我来日本多年了,没有接触国内的IPv4 over IPv6的技术,感觉国内IPv4地址紧张,用的传统NAT和PPPoE非常多,大多数设备还是建立在…

使用 YApi 管理 API 文档,测试, mock

随着互联网的发展,API变的至关重要。根据统计,目前市面上有上千万的开发者,互联网项目超过10亿,保守统计涉及的 API 数量大约有 100 亿。这么大基数的API,只要解决某些共有的痛点,将会是非常有意义的事情。…

开发实战角度:distinct实现原理及具体优化总结

1.背景 Distinct是一种常用的操作,在所有数据库的SQl语言中都是一个非常重要的操作,在Hive中,Distinct去重原理是通过MapReduce来实现的,Distinct操作可以应用于单个列,亦可以应用于多个列。基本原理是将输入的数据集…

机器学习期末复习总结笔记(李航统计学习方法)

文章目录 模型复杂度高---过拟合分类与回归有监督、无监督、半监督正则化生成模型和判别模型感知机KNN朴素贝叶斯决策树SVMAdaboost聚类风险PCA深度学习范数计算梯度下降与随机梯度下降SGD线性回归逻辑回归最大熵模型适用性讨论 模型复杂度高—过拟合 是什么:当模型…

golang通过go-git下载gitlab源码

1 申请令牌 方法1:具体项目下申请: 方法2:全局申请 2 获取token 3 下载代码 package mainimport ("fmt""os""github.com/go-git/go-git/v5" )func main() {_, err : git.PlainClone("/tmp/foo",…

java web mvc-07-Vaadin 入门介绍

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …