为什么浏览器从右到左匹配CSS选择器?

tga*_*ews 543 html css browser css-selectors

CSS选择器由浏览器引擎从右到左匹配.因此,他们首先找到孩子,然后检查他们的父母,看看他们是否符合规则的其余部分.

  1. 为什么是这样?
  2. 是因为规范说的吗?
  3. 如果从左到右进行评估,它是否会影响最终布局?

对我来说,最简单的方法是使用元素数量最少的选择器.首先是ID(因为它们应该只返回1个元素).然后可能是类或具有最少节点数的元素 - 例如,页面上可能只有一个跨度,因此可以使用引用跨度的任何规则直接到达该节点.

以下是备份我的说法的一些链接

  1. http://code.google.com/speed/page-speed/docs/rendering.html
  2. https://developer.mozilla.org/en/Writing_Efficient_CSS

这听起来像这样做是为了避免必须看到父母的所有孩子(可能是很多孩子),而不是一个孩子的所有父母必须是一个孩子.即使DOM很深,它也只会在每个级别查看一个节点而不是RTL匹配中的多个节点.评估CSS选择器LTR或RTL更容易/更快?

Bor*_*sky 811

请记住,当浏览器正在进行选择器匹配时,它有一个元素(它试图确定样式的元素)以及所有规则及其选择器,它需要找到与元素匹配的规则.这与通常的jQuery不同,比如,你只有一个选择器,你需要找到与该选择器匹配的所有元素.

如果您只有一个选择器并且只有一个元素可以与该选择器进行比较,那么在某些情况下从左到右更有意义.但这绝不是浏览器的情况.浏览器正在尝试呈现Gmail或其他任何内容,并且<span>正在尝试设置样式以及Gmail放入其样式表中的10,000多个规则(我没有提供该数字).

特别是,在这种情况下,浏览器正在查看它所考虑的大多数选择器与所讨论的元素匹配.所以问题就变成了决定选择器不尽可能快的问题; 如果在匹配的情况下需要一些额外的工作,由于您在不匹配的情况下保存的所有工作,您仍然会赢.

如果你只是将选择器的最右边部分与你的元素相匹配,那么它很可能无法匹配而且你已经完成了.如果它匹配,你必须做更多的工作,但只与你的树深度成比例,这在大多数情况下并不是那么大.

另一方面,如果你从匹配选择器的最左边部分开始......你对它有什么匹配?您必须开始遍历DOM,寻找可能与之匹配的节点.只是发现最左边的部分没有任何匹配可能需要一段时间.

所以浏览器从右边匹配; 它提供了一个明显的起点,让您可以非常快速地摆脱大多数候选选择器.您可以在http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665上查看一些数据(虽然这种表示法令人困惑),但结果是特别针对Gmail两年前,对于70%的(规则,元素)对,您可以在检查规则最右侧选择器的tag/class/id部分后判断规则不匹配.Mozilla的页面加载性能测试套件的相应数量为72%.因此,尽可能快地摆脱所有规则中的2/3是非常值得的,然后只担心匹配剩余的1/3.

另请注意,浏览器已经进行了其他优化,以避免尝试匹配绝对不匹配的规则.例如,如果最右边的选择器有一个id并且id与元素的id不匹配,那么在Gecko中根本不会尝试将该选择器与该元素匹配:尝试使用"具有ID的选择器"的集合来自元素ID的哈希表查找.因此,在考虑最右边的选择器的标签/类/ id之后,这是70%的具有很好匹配机会的规则仍然不匹配.

  • 请注意,RTL匹配仅适用于[组合器](http://www.w3.org/TR/selectors/#selector-syntax).它不会深入到简单的选择器级别.也就是说,浏览器采用最右边的*复合选择器*或*序列的简单选择器*并尝试以原子方式匹配它.然后,如果匹配,则它将组合子向左跟随*下一个复合选择器*并检查该位置的元素,依此类推.没有证据表明浏览器会读取复合选择器RTL的每个部分; 实际上,最后一段恰恰表示了其他段落(ID检查始终排在第一位). (6认同)
  • 作为一个小小的奖励,即使用英语,读取RTL比使用LTR更有意义.一个例子:http://stackoverflow.com/questions/3851635/css-combinator-precedence/3851754#3851754 (5认同)
  • 实际上,当你匹配选择器时,至少在Gecko中,标记名和命名空间是第一位的.id(以及标记名和类名)在预过滤步骤中被考虑,该步骤消除了大多数规则,而没有真正尝试匹配选择器. (5认同)

aWe*_*per 32

从右到左解析,也称为自下而上解析实际上对浏览器有效.

考虑以下:

#menu ul li a { color: #00f; }
Run Code Online (Sandbox Code Playgroud)

该浏览器首先检查a,然后li,然后ul,然后#menu.

这是因为当浏览器正在扫描页面时,它只需要查看当前元素/节点以及它已扫描的所有先前节点/元素.

需要注意的是,浏览器开始处理它获得完整标记/节点的时刻,除了找到脚本之外不需要等待整个页面,在这种情况下它暂时暂停并完成脚本的执行然后前进.

如果反之亦然,那将是低效的,因为浏览器在第一次检查时发现了它正在扫描的元素,但后来被迫继续查看所有其他选择器的文档.为此,浏览器需要拥有整个html,并且可能需要在开始css绘制之前扫描整个页面.

这与大多数lib解析dom的方式相反.在那里构建了dom,它不需要扫描整个页面,只需找到第一个元素,然后继续匹配其中的其他元素.


Gre*_*mer 20

它允许从更具体到更具体的级联.它还允许应用中的短路.如果更具体的规则适用于父规则适用的所有方面,则忽略所有父规则.如果父级中还有其他位,则应用它们.

如果你反过来,你会根据父母进行格式化,然后每当孩子有不同的东西时覆盖.从长远来看,这比忽略已经处理的规则中的项目要多得多.

  • 这是一个单独的问题.您通过按特异性排序规则然后按特定顺序对它们进行匹配来进行级联.但这里的问题是为什么对于给定的规则,您以特定的方式匹配其选择器. (11认同)