浏览器如何读取和解释CSS?

31

两个问题:

  1. 浏览器是否像JavaScript一样内置了CSS解释器?
  2. 浏览器什么时候读取CSS以及何时应用CSS?

具体来说,我想澄清JavaScript和CSS之间的区别或原因,即您需要专门等到window.onload以使解释器能够正确地getElementById。但是,在CSS中,您可以随意选择和应用样式类和ID。

(如果这有任何影响,请假设我指的是在头部拥有外部样式表的基本HTML页面)

7个回答

36
CSS渲染是一个有趣的话题,所有竞争对手都在努力加快视图层(HTML和CSS)的渲染速度,以便在眨眼之间向最终用户提供最佳结果。
首先,是的,不同的浏览器有自己的CSS解析器/渲染引擎。
  • Google Chrome,Opera(版本15) - 使用称为BlinkWebkit分支渲染引擎
  • Safari - 使用Webkit(现在已分叉为Webkit2
  • Internet Explorer - 使用Trident渲染引擎。 (+更新:Windows 10上的Edge将在未来版本中使用Chromium分支
  • Mozilla Firefox - 使用Gecko引擎

所有这些渲染引擎都包含CSS解释器和HTML DOM解析器

所有这些引擎都遵循以下列出的模型,这些是W3C标准的一部分。

注意:所有这些模型都相互关联且相互依赖。它们不是定义呈现CSS标准的单独模型。这些模型阐明了如何基于优先级(例如内联样式、特定性等)处理CSS。


解释:


阶段 1:


所有浏览器都会从服务器下载HTML和CSS脚本,并通过解析HTML标签将它们转换为称为内容树的树形结构中的DOM节点。
当HTML文档被解析时,浏览器渲染引擎会构建另一棵树,称为渲染树。该树是按照将要显示的顺序排列的可视元素。
Firefox称其为frames,而Webkit团队则称其为Renderer或Renderer对象。
请参见下面的图像:(来源:HTML5 Rocks

enter image description here


阶段2:


在上述过程之后,这两棵树都要经历布局处理,即浏览器告诉视口在屏幕上放置每个节点的位置。
这被定义为W3C的定位方案(点击链接获取详细信息),它指示浏览器如何在哪里放置元素。以下是三种类型:
  • 正常流
  • 浮动
  • 绝对定位

第三阶段:


现在是最后一个阶段,称为绘画。这是一个逐步的过程,其中渲染引擎遍历每个渲染树节点,并使用UI后端层将它们视觉上呈现出来。此时应用所有的视觉特效,如字体大小、背景颜色、表格绘制等。

注意:如果您尝试在缓慢的连接上打开任何网页,则可以清楚地观察到此阶段。为了获得更好的用户体验,大多数现代浏览器会尽快显示元素。这给用户留下了印象,即页面正在加载并且必须等待完成。


更好理解的工作流程图

来源 HTML5 Rocks

  • Webkit:

enter image description here

Mozilla的Gecko引擎: 在此输入图像描述

参考资料:(请阅读以下链接。它们是与此主题相关的最佳资源)


(以上为编程相关内容的链接列表,包括浏览器工作原理、渲染机制、HTML和CSS的解析等)

根据这个流程,如果在选择器的开头声明了颜色、背景颜色等属性,并在结尾声明了定位和大小,那么浏览器渲染CSS会变慢吗? 我很好奇属性定义的顺序是否会影响渲染速度,如果有影响,那么影响是什么? - Nishutosh Sharma
通常CSS是从下往上解释的。有些浏览器采用自上而下的方法。建议使用CSS预处理器,如LESS或SASS,因为这些工具可以帮助您编写高效的CSS。顺序和方案不会影响速度,除非您不必要地重复覆盖样式的代码,而是创建视觉错误,例如在Jquery移动中著名的页脚固定问题。 - NiRUS
1
这应该是被接受的答案。它更加详细和完整。 - Zorgatone
gecko的链接好像已经失效了。 - Hacker
@Hacker 更新了它。 - NiRUS

11

如果您最近使用过较慢的连接,您会发现随着DOM结构加载,CSS将应用于元素,并实际重新排列页面内容。由于CSS不是一种编程语言,它不依赖于在特定时间可用的对象来正确解析(JavaScript),因此浏览器可以通过为新元素应用样式来重新评估页面结构以检索更多HTML。

也许这就是为什么即使是今天,移动Safari的瓶颈并非始终是3G连接,而是页面渲染。


那么,澄清一下,浏览器是按元素基础循环遍历CSS选择器,而不是按选择器基础循环遍历HTML元素? - chharvey
1
不,浏览器以阻塞方式下载和解释CSS,一次性消耗整个CSS语句或外部文件。因此,如果您的CSS位于头部,则在呈现之前进行处理。然后,随着HTML元素的流入和解释,浏览器不断地对这些元素应用样式,因为它们被发现。 - Aaron

7

是的,浏览器内置了CSS解释器。你不需要“等待window.onload”的原因是:尽管JavaScript是一种图灵完备的命令式编程语言,但CSS只是一组样式规则,浏览器会将它们应用于匹配的元素。


6
浏览器从右到左读取CSS代码,这是Google和Mozilla都认可的。Google在http://code.google.com/speed/page-speed/docs/rendering.html中说:“引擎会从右到左评估每个规则”,Mozilla在https://developer.mozilla.org/en/Writing_Efficient_CSS中说:“样式系统通过首先匹配关键选择器,然后向左移动来匹配规则”。以'.item h4'为例,浏览器首先搜索页面上所有'h4'标签,然后查找是否有带有“item”类名的父元素,如果找到,就应用CSS规则。

很好的回答,但它并没有解释浏览器何时执行此操作。它是解析CSS文件,查看.item h4,循环遍历所有HTML元素,然后应用样式,然后继续下一个CSS选择器吗?还是先解析HTML,然后循环遍历CSS选择器,匹配.item h4,然后移动到下一个元素? - chharvey
换句话说,它是按选择器基础循环遍历HTML元素,还是按元素基础循环遍历CSS选择器? - chharvey

5
我最近在Google页面速度上发现了这篇文章:
当浏览器解析HTML时,它构建一个内部文档树来表示所有要显示的元素。然后,根据标准CSS级联、继承和排序规则,将元素与各种样式表中指定的样式进行匹配。在Mozilla的实现(可能也包括其他实现)中,对于每个元素,CSS引擎会搜索样式规则以找到匹配项。引擎从右到左评估每个规则,从最右边的选择器(称为“键”)开始,并通过每个选择器移动,直到找到匹配项或丢弃该规则。(“选择器”是应用规则的文档元素。)
参考链接:http://code.google.com/speed/page-speed/docs/rendering.html

4
这是我发现的关于浏览器如何处理 HTML 和 CSS 的最佳描述:
渲染引擎将开始解析 HTML 文档,并将标签转换为 DOM 节点,形成名为“内容树”的树。它将解析样式数据,包括外部 CSS 文件和样式元素。样式信息与 HTML 中的视觉指令将一起用于创建另一棵树 - 渲染树。
一般来说,渲染引擎的工作包括:
  • 将规则标记化(将输入分解为标记,也称为词法分析器)
  • 通过分析文档结构根据语言语法规则构建解析树

CSS解析器

与HTML不同,CSS是一个无上下文语法(带有确定性语法)。
因此,我们将有CSS规范定义CSS词法和语法语法, 解析器通过样式表进行应用。

每个标记的词汇语法由正则表达式定义:

comment     \/\*[^*]*\*+([^/*][^*]*\*+)*\/
num     [0-9]+|[0-9]*"."[0-9]+
nonascii    [\200-\377]
nmstart     [_a-z]|{nonascii}|{escape}
nmchar      [_a-z0-9-]|{nonascii}|{escape}
name        {nmchar}+
ident       {nmstart}{nmchar}*
< p > "ident"代表标识符,例如类名。“name”是一个元素的id(可以通过“#”引用)

语法规则在BNF中描述。

ruleset
  : selector [ ',' S* selector ]*
    '{' S* declaration [ ';' S* declaration ]* '}' S*
  ;
selector
  : simple_selector [ combinator selector | S+ [ combinator selector ] ]
  ;
simple_selector
  : element_name [ HASH | class | attrib | pseudo ]*
  | [ HASH | class | attrib | pseudo ]+
  ;
class
  : '.' IDENT
  ;
element_name
  : IDENT | '*'
  ;
attrib
  : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
    [ IDENT | STRING ] S* ] ']'
  ;
pseudo
  : ':' [ IDENT | FUNCTION S* [IDENT S*] ')' ]
  ;

如果您想了解浏览器工作流程的详细描述,请查看此文章


这篇文章提到WebKit使用Flex和Bison解析器生成器自动从CSS语法文件创建解析器。但我无法找到那些语法文件,你有什么想法吗?我也在http://stackoverflow.com/questions/31721308/where-can-i-find-webkits-css-grammar-files上发布了这个正式问题。 - John Slegers

0

我相信浏览器会按照它找到的顺序解释CSS,这样在body中的CSS(内联)优先于head中的CSS(包括外部CSS)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接