作为前端,我们每天都和CSS打交道,那么CSS的原理是什么?1、在浏览器渲染之初,我们还是不厌其烦的回顾一下浏览器的渲染过程。一、上图:如上图所示,我们的浏览器渲染过程分为两条主线:一是HTMLParser生成的DOM树;二、CSSParser生成的StyleRules;之后,DOM树和StyleRules会生成一个新的对象,也就是我们常说的RenderTree渲染树,结合Layout绘制到屏幕上进行显示。这篇文章的重点也在第二个分支,我们来探究一下CSS解析的原理。2、WebkitCSSparser浏览器CSS模块,负责解析CSS脚本,计算每个Element的样式。CSS模块虽然小,但计算量大,设计不当往往成为浏览器性能的瓶颈。CSS模块的实现有几个特点:CSS对象多(小且颗粒多)、计算频繁(为每个Element计算样式)。这些特点决定了webkit在实现CSS引擎时采用的设计和算法。如何高效地计算样式是浏览器内核的重点和难点。先看一张图:Webkit使用Flex和Bison解析器生成器,自动从CSS语法文件生成解析器。它们都是将每个CSS文件解析成一个样式表对象,每个对象包含CSS规则,CSS规则对象包含选择器和声明对象,以及其他一些符合CSS语法的对象,下图可能更清楚:Webkit使用自动编码generation工具生成相应的代码,也就是说自动生成词法分析和语法分析代码,Webkit中实现的CallBack函数在CSSParser中。CSS的一些解析函数的入口也在这里,它们会调用lex、parse等生成代码。相比之下,生成代码中需要的CallBack也需要在这里实现。例如,现在我们看其中一个回调函数createStyleRule()的实现,当需要创建通用规则时会调用该函数,代码如下:CSSRule*CSSParser::createStyleRule(CSSSelector*selector){CSSStyleRule*规则=0;如果(选择器){rule=newCSSStyleRule(styleElement);m_parsedStyleObjects。追加(规则);规则->setSelector(sinkFloatingSelector(selector));rule->setDeclaration(newCSSMutableStyleDeclaration(rule,parsedProperties,numPars));}清除属性();退货规则;从这个函数的实现可以清楚的看出,当解析器满足某种条件,需要创建一个CSSStyleRule时,就会调用这个函数。该函数的作用是创建一个CSSStyleRule,并设置它添加解析后的样式对象列表m_parsedStyleObjects,其中对象指的是Rule。这样,经过这样的解析,输入的样式表中的所有StyleRules都会被转换成Webkit内部的模型对象CSSStyleRule对象,保存在m_parsedStyleObjects中,它是一个Vector。但是我们要分析的结果是什么呢?1、通过调用CSSStyleSheet的parseString函数开始上述CSS解析过程。解析一次后,将Rules存放到对应的CSSStyleSheet对象中;2、由于现在的规则还是不好处理,需要转成CSSRuleSet。即把所有的纯样式规则存放在对应的集合中,这个集合的抽象就是CSSRuleSet;3、CSSRuleSet提供了一个addRulesFromSheet方法,可以将CSSStyleSheet中的规则转换为CSSRuleSet中的规则;4.根据这些CSSRuleSet来确定每个页面中元素的样式;3.CSS选择器解析顺序很多同学可能都知道,排版引擎是从右到左解析CSS选择器的。为什么是这样?1.解析HTML生成DOMTree(我们比较熟悉);CSS解析完成后,需要将解析结果连同DOMTree的内容一起分析构建RenderTree,最终用于绘制。RenderTree中的元素(在WebKit中称为“renderers”,在Firefox中称为“frames”)与DOM元素一一对应,但不是一一对应的:一个DOM元素可能对应多个renderer,比如textwrapping,不同的“rows”"将成为渲染树中的不同渲染器。某些DOM元素会被RenderTree完全忽略,例如display:none元素。2、在创建RenderTree(WebKit中的“Attachment”过程)时,浏览器必须根据CSS分析结果(StyleRules)来决定为DOMTree中的每个元素生成什么样的renderer。对于每个DOM元素,必须在所有样式规则中找到匹配的选择器,并且必须合并相应的规则。选择器的“解析”其实就是在这里进行的。在遍历DOMTree时,从StyleRules中找到对应的选择器。3、因为所有样式规则的数量可能很多,而且大部分都不会匹配到当前DOM元素(因为数量多,一般会建一个规则索引树),所以有个快速判断的方法“此选择器与当前元素不匹配”非常重要。4、如果是正向分析,比如“divdivpem”,我们首先需要检查当前元素到html的整个路径,找到最上面的div,然后往下看,如果不匹配,就要返回bottom上层的div往下匹配selector中的第一个div,还需要往回走几次才能判断是否匹配,效率很低。对于上面的描述,我们先有个大概的了解。接下来我们看这样一个例子,参考地址:
span>111span>
span>222span>
333
- 1超酷的弧形智能手表让其他设计师都为三星着急
- 2都说VR雷声大雨点小 万没想到索尼PS VR竟这么火
- 3腾讯、京东、苏宁等都争相支持乐视,他们的计划是什么?
- 4连想都不敢想吗?我们来看看现在孩子们使用的教育智能硬件
- 5里里外外都很漂亮!智能穿戴走上奢华路线
- 6这个夏天,所有的女孩都没有她那么“好看”
- 7都说VR头显没机会创业了,为什么还在做
- 8不知道2016年初有这些新的VR产品吗?那么饭前饭后都聊些什
- 9这款智能耳机真正防水,连游泳都不需要耳塞
- 10这些牛仔裤一年四季都可以穿,而且可以自动调节温度,非常方便
- 11苹果要疯了! iWatch什么都没有吗?
- 12女性眼中的智能手表!只要外表够了,其他的都可以忽略吗?
- 13每一次创新都引领华为nova 3开启预售
- 14万众期待的谷歌智能手表Pixel Watch,你想知道的所有
- 15简单好携带的VR头盔来了,随时随地都可以玩
- 16当每个人都拥有智能手机时,为什么我们还需要佩戴手表?
- 17这都是苹果的错, Lightning接口耳机比iPhone
- 18谷歌在CES 2019上的10大亮点,每一个都与谷歌语音助手
- 19三星和LG都陷入了困境,智能手表该不该独立通话?
- 20诺基亚手表曝光!在苹果之前和之后,都有三星,诺基亚能否延续“