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

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

  1. 为什么会这样?
  2. 只是因为说明书这么说吗?
  3. 如果从左到右计算,会影响最终的布局吗?

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

这里有一些链接支持我的观点

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

听起来,这样做是为了避免查看parent的所有子结点(可能有很多),而不是查看child的所有父结点(必须是一个)。即使DOM是深度的,它也只会在RTL匹配中每层查找一个节点,而不是多个。# EYZ0

79946 次浏览

它允许从更具体的级联到不太具体的级联。它还允许在应用中短路。如果更具体的规则应用于父规则应用的所有方面,则所有父规则都将被忽略。如果父节点中有其他位,则应用它们。

如果你反过来,你会根据父文件格式化然后每次子文件有不同的内容时都重写。从长远来看,这比忽略规则中已经处理好的项要多得多。

请记住,当浏览器进行选择器匹配时,它有一个元素(它试图确定样式的元素)和所有的规则及其选择器,它需要找到哪些规则与元素匹配。这与通常的jQuery不同,在jQuery中,您只有一个选择器,并且需要找到与该选择器匹配的所有元素。

如果只有一个选择器,并且只有一个元素与该选择器进行比较,那么在某些情况下,从左到右更有意义。但这显然是浏览器的情况。浏览器试图呈现Gmail或任何东西,并有一个<span>,它试图样式和Gmail放在它的样式表中的10,000+规则(我没有编这个数字)。

特别是,在浏览器查看大多数选择器的情况下,它认为与问题中的元素匹配。所以问题就变成了决定选择器是否匹配得尽可能快;如果这需要在匹配的情况下做一些额外的工作,你仍然会赢,因为你在不匹配的情况下节省了所有的工作。

如果你一开始只是匹配选择器最右边的部分,那么它很可能不匹配,你就完成了。如果匹配,则必须做更多的工作,但只与树深度成正比,在大多数情况下树深度并不大。

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

浏览器从右边匹配;它提供了一个明显的起点,并允许您非常快速地摆脱大多数候选选择器。您可以在http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665处看到一些数据(尽管符号令人困惑),但结果是,对于Gmail,特别是两年前的Gmail,对于70%的(rule, element)对,您可以在检查规则最右边选择器的tag/class/id部分后确定规则不匹配。Mozilla页面负载性能测试套件的相应数字为72%。因此,尽快摆脱这2/3的规则是值得的,然后只担心匹配剩下的1/3。

还要注意,浏览器已经做了其他优化,以避免尝试匹配肯定不匹配的规则。例如,如果最右边的选择器有id,而id与元素的id不匹配,那么在Gecko中就不会尝试将该选择器与该元素匹配:尝试的“带id的选择器”集来自元素id上的哈希表查找。因此,在只考虑最右边选择器的标签/类/id后,有70%的规则有很好的机会匹配仍然

从右向左解析(也称为自底向上的语法分析)对于浏览器来说实际上是高效的。

考虑以下几点:

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

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

这是因为当浏览器扫描页面时,它只需要查看当前的元素/节点和它扫描过的所有之前的节点/元素。

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

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

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