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

时间:2011-04-26 22:03:36

标签: html css browser css-selectors

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

  1. 这是为什么?
  2. 只是因为规范说明了吗?
  3. 如果从左到右进行评估,是否会影响最终布局?
  4. 对我而言,最简单的方法是使用元素数量最少的选择器。首先是ID(因为它们应该只返回1个元素)。然后可能是类或具有最少节点数的元素 - 例如页面上可能只有一个范围,因此可以使用引用范围的任何规则直接转到该节点。

    以下是备份我的声明的一些链接

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

    3. 听起来这样做是为了避免必须看到父母的所有孩子(可能很多),而不是一个孩子的父母必须是一个孩子。即使DOM很深,它也只会在每个级别查看一个节点而不是RTL匹配中的多个节点。 Is it easier/faster to evaluate CSS selectors LTR or RTL?

3 个答案:

答案 0 :(得分:794)

请记住,当浏览器进行选择器匹配时,它有一个元素(它试图确定样式的元素)以及所有规则及其选择器,它需要找到与元素匹配的规则。这与通常的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%的规则很可能匹配仍然不匹配。

答案 1 :(得分:27)

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

请考虑以下事项:

#menu ul li a { color: #00f; }

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

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

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

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

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

答案 2 :(得分:19)

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

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