写了这么多class,color,background,display...
; 也许有时候会疑惑,怎么就显示在页面上,改变元素的样式。css
本文简明介绍整个解析,匹配,渲染过程html
css 是Cascading Style Sheets的简写,是一种样式表语言。对应多种语法规则,能够为HTML 指定样式。前端
图片来源。 html5
css 规则由两部分组成:选择器
和 声明
。上图中element
对应的类选择器
,紧接着声明(Declaration)
。web
每条声明由一个属性(Property)
加冒号(:)
和 一个值(value)
加分号(;)
组成。chrome
解析 html 或外部css 文档,就是将文档转化成为有意义的结构,可以让代码理解。解析结果表明了文档结构的节点树,浏览器
解析分为词法分析 和 语法分析。性能优化
词法分析,也是编译原理中的术语,从左到右一个字符一个字符的读入源程序,对字符流进行扫描,根据构词规则识别单词,。这一过程可使用lex等工具自动生成。app
语法分析,主要任务是在词法分析的基础上,将单词序列组合成各种语法短语,如“程序”, “语句”,“表达式”dom
解析工做一般会被拆分为两个组件:
具体到css解析,由于它是上下文无关的语法,能够利用各类解析器进行解析。webkit 使用Flex 和 Bison 解析器生成器,经过css 语法文件自动建立解析器。解析器将CSS文件解析成StyleSheet对象,且每一个对象都包含CSS规则。CSS规则包含选择器和声明对象。
上图是 一个像素点的一辈子的ppt中选出图片,感兴趣能够看看演讲视频,很是直白,css样式规则会被各类方式索引以便进行快速有效的查找。实现各个样式属性的C++ 类,好比ppt中的BorderLeftColor类,是在构建时Python脚本自动生成的。
具体到代码实现中,webkit 使用CSSRuleSet 对象来保存style rule,在通常规则须要建立时,调用createStyleRule();
在使用css选择器进行样式匹配时,尽可能少用层级关系,由于这样能够减小选择器匹配的次数,提升css 解析效率。
其实浏览器使用从右到左的解析顺序,一样提升了效率。一般在写css 样式时,咱们一向的想法是,从左往右解析,从根节点开始,一层一层遍历匹配,直到全部的选择器都匹配上了。浏览器解析的顺序正好相反。
简单回顾下本次话题的上下文,也就是浏览器对页面解析过程:
HTML parser
生成 Dom Tree
css parser
生成 style rules
,也就是CSSOM tree。Dom
与 CSSOM
匹配完成后,最后结合生成render tree
。根据这张图,能够对渲染过程大体了解。
回到浏览器匹配css 规则上,若是只有一个选择器 对应匹配一个元素,从左往右匹配看似很是合理,可是正常状况是,一个dom节点,好比<div class="cls1 cls2 cls3" id='id1'></div>
,可能对应了无数个css规则,没有上限,我能够在上面加很是多的样式。css 匹配效率的关键就是如何快速判断尽量多的选择器并不能匹配。
先看看有多层嵌套的css规则。好比 #root .box .wrap i {}
, 若是从左往右解析,最左边开始, 直到最右边的选择器i, dom节点上根本没有i
标签, 遍历到最后才排除css 规则。
相反,从最右边的选择器部分开始匹配,若是不成功,整个匹配过程就能够马上结束;成功了,继续往左,匹配父节点,跟树的深度成正比。因此浏览器的匹配方式,能够很是快速的排除大部分的选择器。
根据2009年在Firefox上作的测试,结论是仅仅从最右边的选择器开始检查,就能够排除70%的规则。快速除去2/3的css规则后,后面只用担忧剩余的1/3。
从css文档被解析器解析完成,将数据保存在对象模型中,获取全部已解析的样式规则,结合浏览器提供的默认样式,计算出每一个DOM 元素最终的样式值。保存在ComputedStyle对象模型中,它是由样式属性和值造成的map。
而且getComputedStyle 已经暴露出来,在js中经过window.getComputedStyle
,能够获取元素的最终样式。
若是多个element的computedStyle不经过计算能够确认它们相等,那么这些elements只会计算一次样式,其他的直接共享该ComputedStyle。
那些规则会共享computedStyle(待验证):
不能有style 属性,哪怕style 属性相同。他们也不会共享。
<p style="color:red">p1</p> <p style="color:red">p2</p>
页面绘制到屏幕后,页面结构的改变也有可能致使渲染树从新计算,其中重排和重绘是最耗时的部分。
在页面的生命周期中,随时都有可能发生重排(Layout)和重绘(Painting)
当可见节点位置 及尺寸发生变化时都会发生重排,并且重排开销比重绘更大。
至少会有一次重排,发生在初始化页面布局的时候。
触发重排的几种状况:
改变元素的外观属性(如background-color, border-color, visibility),不影响整个布局,浏览器就会根据元素的新属性从新绘制。
重绘不会带来从新布局
DOM树中每一个节点的都对应一个LayoutObject, 拥有相同的坐标空间的LayoutObject,属于同一渲染层(RenderLayers)。
渲染层保证元素按照正确顺序合成(composite),正常展现元素的重叠以及元素透明等。
存在一些特殊状况,为知足指定条件的LayoutObject会拥有独立的渲染层,其余layoutobject则和第一个拥有渲染层的父元素公用一个。
打开Chrome Devtools,按下Esc建
在出现的面板上 点击左上角三点。
选择rendering,转到对应标签。
打开后,页面中闪烁的绿色区域,表示这块须要从新绘制。
当滚动侧边栏时,会出现整块绿色
本文对css整个渲染过程进行简单介绍,试图把大量复杂知识点串在一块儿,至少可让平时跟css打交道的咱们,了解大体是个什么过程,同时也是对本身学习过程当中的一次总结。对于里面涉及到的概念,均可以做为一个切入点,去好好研究。