资讯专栏INFORMATION COLUMN

从css到页面样式渲染

Nekron / 1141人阅读

摘要:对应多种语法规则可以为指定样式。渲染页面绘制到屏幕后,页面结构的改变也有可能导致渲染树重新计算,其中重排和重绘是最耗时的部分。

写了这么多class,color,background,display...; 也许有时候会疑惑,怎么就显示在页面上,改变元素的样式。

本文简明介绍整个解析,匹配,渲染过程

css 描述

css 是Cascading Style Sheets的简写,是一种样式表语言。对应多种语法规则,可以为HTML 指定样式。

基本规则

图片来源。

css 规则由两部分组成:选择器声明。上图中element 对应的类选择器,紧接着声明(Declaration)

每条声明由一个属性(Property)冒号(:)和 一个值(value)分号(;) 组成。

CSS 解析

解析 html 或外部css 文档,就是将文档转化成为有意义的结构,能够让代码理解。解析结果代表了文档结构的节点树,

解析分为词法分析 和 语法分析。

词法分析,也是编译原理中的术语,从左到右一个字符一个字符的读入源程序,对字符流进行扫描,根据构词规则识别单词,。这一过程可以使用lex等工具自动生成。

语法分析,主要任务是在词法分析的基础上,将单词序列组合成各类语法短语,如“程序”, “语句”,“表达式”

解析工作通常会被拆分为两个组件:

词法分析器,负责将输入流分解成有效的字符。

解析器,负责根据不同语言的语法规则来分析文档结构,最后构造出解析树。
词法分析器知道如何去除不相关的字符,比如空格和换行

具体到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。

DomCSSOM匹配完成后,最后结合生成render tree

根据 render tree 开始 布局
...

根据这张图,可以对渲染过程大致了解。

回到浏览器匹配css 规则上,如果只有一个选择器 对应匹配一个元素,从左往右匹配看似非常合理,但是正常情况是,一个dom节点,比如

,可能对应了无数个css规则,没有上限,我可以在上面加非常多的样式。css 匹配效率的关键就是如何快速判断尽可能多的选择器并不能匹配。

先看看有多层嵌套的css规则。比如 #root .box .wrap i {}, 如果从左往右解析,最左边开始, 直到最右边的选择器i, dom节点上根本没有i标签, 遍历到最后才排除css 规则。

相反,从最右边的选择器部分开始匹配,如果不成功,整个匹配过程就可以立刻结束;成功了,继续往左,匹配父节点,跟树的深度成正比。所以浏览器的匹配方式,可以非常快速的排除大部分的选择器。

根据2009年在Firefox上做的测试,结论是仅仅从最右边的选择器开始检查,就可以排除70%的规则。快速除去2/3的css规则后,后面只用担心剩余的1/3。

样式作用在DOM元素上

从css文档被解析器解析完成,将数据保存在对象模型中,获取所有已解析的样式规则,结合浏览器提供的默认样式,计算出每个DOM 元素最终的样式值。保存在ComputedStyle对象模型中,它是由样式属性和值形成的map。
并且getComputedStyle 已经暴露出来,在js中通过window.getComputedStyle,可以获取元素的最终样式。

共享ComputedStyle

如果多个element的computedStyle不通过计算可以确认它们相等,那么这些elements只会计算一次样式,其余的直接共享该ComputedStyle。

那些规则会共享computedStyle(待验证):

该共享的element不能有id 属性且CSS中还有该id的StyleRule,即使StyleRule 与 element 不匹配

tagName 和 class 属性必须一样。

mappedAttribute 必须相同。

不能使用sibling selector, 比如 :first-child, :last-child.

不能有style 属性,哪怕style 属性相同。他们也不会共享。

   

p1

p2

渲染

页面绘制到屏幕后,页面结构的改变也有可能导致渲染树重新计算,其中重排和重绘是最耗时的部分。

在页面的生命周期中,随时都有可能发生重排(Layout)和重绘(Painting)

重排(reflow)

当可见节点位置 及尺寸发生变化时都会发生重排,而且重排开销比重绘更大。

至少会有一次重排,发生在初始化页面布局的时候。

触发重排的几种情况:

添加或删除可见dom元素

元素位置改变

元素尺寸改变,

文字,内容,字体发生改变

页面初始化渲染
....

重绘(repaints)

改变元素的外观属性(如background-color, border-color, visibility),不影响整个布局,浏览器就会根据元素的新属性重新绘制。

重绘不会带来重新布局

层合成(composite)

DOM树中每个节点的都对应一个LayoutObject, 拥有相同的坐标空间的LayoutObject,属于同一渲染层(RenderLayers)。

渲染层保证元素按照正确顺序合成(composite),正常展示元素的重叠以及元素透明等。

存在一些特殊情况,为满足指定条件的LayoutObject会拥有独立的渲染层,其他layoutobject则和第一个拥有渲染层的父元素公用一个。

利用chrome Devtools查看绘制过程。

打开Chrome Devtools,按下Esc建
在出现的面板上 点击左上角三点。

选择rendering,转到对应标签。

打开后,页面中闪烁的绿色区域,表示这块需要重新绘制。
当滚动侧边栏时,会出现整块绿色

总结

本文对css整个渲染过程进行简单介绍,试图把大量复杂知识点串在一起,至少可以让平时跟css打交道的我们,了解大致是个什么过程,同时也是对自己学习过程中的一次总结。对于里面涉及到的概念,都可以作为一个切入点,去好好研究。

参考链接

Things nobody ever taught me about CSS

缩小样式计算的范围并降低其复杂性

为什么浏览器读取css规则的顺序是从右到左

why-do-browsers-match-css-selectors-from-right-to-left

【Hello CSS】第一章-CSS的语法与工作流

编译原理之词法分析、语法分析、语义分析

How Browsers Work: Behind the scenes of modern web browsers

前端代码如何通过浏览器演化为屏幕显示的像素

Webkit CSS引擎分析

简化绘制的复杂度、减小绘制区域

无线性能优化:Composite

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116084.html

相关文章

  • 浏览器前端优化

    摘要:幸运的是,浏览器行为的基础原理是相当稳定而且文档齐全的,并且在相当长一段时间内肯定不会发生显著变化。浏览器有种称为预加载扫描器的东西,它会扫描的脚本,并开始预加载脚本,不过脚本只会在先前的节点已经构建完成后,才会依次执行。 本文转载自:众成翻译译者:网络埋伏纪事链接:http://www.zcfy.cc/article/2847原文:https://hackernoon.com/opt...

    yimo 评论0 收藏0
  • 浏览器渲染页面过程与页面优化

    摘要:由一道面试题引发的思考从用户输入浏览器输入到页面最后呈现有哪些过程一道很常规的题目,考的是基本网络原理,和浏览器加载,过程。所以抽出时间研究下浏览器渲染页面的过程。 由一道面试题引发的思考: 从用户输入浏览器输入url到页面最后呈现 有哪些过程?一道很常规的题目,考的是基本网络原理,和浏览器加载css,js过程。 答案大致如下: 用户输入URL地址 浏览器解析URL解析出主机名 浏览...

    djfml 评论0 收藏0
  • CSS 加载新方式

    摘要:二目前最先进的加载方法在上面的代码中,通过一些内联样式我们可以加速初始渲染,同时隐藏起还没有加载完样式的组件,并通过异步地完成加载。 Chrome 浏览器有意改变的加载方式,当其出现在中时,这一变化将更加明显。笔者决定在本文中进行详细说明这种改变可能带来影响与好处。 一.目前CSS文件的加载方式 …content… CSS 会阻碍渲染,因此在all-of-my-st...

    wthee 评论0 收藏0
  • 翻译 | 关键CSS和Webpack: 减少阻塞渲染CSS的自动化解决方案

    摘要:我们可以做很多事情来减少阻塞渲染的,例如,缓存等。但是如何减少阻塞渲染的为此,可以拆分并优先加载首次渲染所需要的关键,然后再加载其它。请注意,文件在标签里引入,因此将会阻塞渲染。 showImg(https://segmentfault.com/img/remote/1460000011503289?w=600&h=321); 原文地址: Critical CSS and Webpa...

    Backache 评论0 收藏0
  • JavaScript工作原理(十):渲染引擎和优化性能的技巧

    摘要:渲染引擎的概述渲染引擎的主要职责是在浏览器屏幕上显示请求的页面。中,渲染树中的每个节点都被称为的渲染器或渲染对象。坐标系相对于根渲染器。增量只有一些渲染器以不影响整个树的方式进行更改。渲染器使其矩形在屏幕上无效。 到目前为止,在我们之前的JavaScript工作原理系列文章中,我们一直关注JavaScript作为一种语言,其功能,它如何在浏览器中执行,如何优化等等。 但是,当您构建We...

    xingqiba 评论0 收藏0

发表评论

0条评论

Nekron

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<