css - 选择器引擎朝哪个方向准确读取?

标签 css css-selectors

我一直相信(尽管我现在怀疑这些信念的有效性):

div.name


速度比:

.name


但是,最近我读到大多数CSS选择器引擎都是从右向左读取的,在这种情况下,第一个示例实际上不会更慢吗?因为选择器引擎会简单地找到每个具有一类名称的元素,然后必须识别出哪些是div

CSS选择器引擎通常阅读哪种方式?从左到右还是从右到左?如果他们通常从右到左阅读,是否有人可以向我解释原因(我看不到从选择器引擎的角度来从右向左阅读有何意义)?

最佳答案

但是我最近读到,大多数CSS选择器引擎都是从右到左读取的,在这种情况下,第一个示例实际上不会更慢吗?
  
  大致了解CSS选择器引擎的哪种方式?从左到右还是从右到左?并且,如果他们通常从右到左阅读,是否有人可以向我解释原因(我看不到从选择器引擎的角度来从右向左阅读有何意义)?


坦白说,要确定哪个选择器在给定的浏览器中变慢,几乎不可能。性能趋于波动并且不可预测,尤其是在这种微观规模和不可预测的文档结构下。即使我们讨论理论性能,它最终也取决于实现。

话虽如此,如Boris Zbarsky's answer to this other questionGuffa's answer to yours所示,典型的浏览器(当前适用于所有主要布局引擎)采用一个元素并评估所有候选选择器以查看其匹配的选择器,而不是查找一个与给定选择器匹配的元素集。这是一个微妙但非常重要的区别。鲍里斯(Boris)提供的技术说明不仅详细到令人难以置信,而且权威性强(在他使用Firefox使用的引擎Gecko的过程中),所以我强烈建议您阅读它。

但是我认为我应该解决您的问题中似乎另一个需要关注的问题:


  因为选择器引擎会简单地找到每个具有一类名称的元素,然后必须标识哪些是div


以及Patrick McElhaney's comment


  链接的问题解释了为什么选择器通常是从右到左读取的,所以#foo ul.round.fancy li.current是从li.current, ul.round.fancy, #foo读取的,但是它真的在每个元素(.current, li, .fancy, .round, ul, #foo)中从右到左读取吗?应该吗


我从未实现CSS,也从未见过其他浏览器如何实现CSS。从上面链接的答案中我们确实知道,浏览器使用从右到左的匹配来遍历选择器中的组合器,例如本示例中的>组合器:

section > div.second > div.third


如果元素不是div.third,则没有检查它的父元素是div.second父元素是section的点。

但是,我不相信这种从右到左的顺序会一直向下钻到简单的选择器级别。换句话说,我不认为浏览器会在从右到左求值的一系列简单选择器序列(也称为复合选择器)的每个部分中使用从右到左的求值方式,这些选择器序列由组合器。

例如,考虑以下人为设计和高度夸大的选择器:

div.name[data-foo="bar"]:nth-child(5):hover::after


现在,不能保证浏览器一定会按照以下顺序检查元素的这些条件:


指针是否在此元素上?
此元素是其父项的第5个孩子吗?
此元素是否具有值为data-foobar属性?
此元素是否具有name类?
这是div元素吗?


除了在选择器上杂乱无章的简单选择器之外,该选择器在功能上与上面的相同,也不必按以下顺序进行评估:

div:hover[data-foo="bar"].name:nth-child(5)::after



此元素是其父项的第5个孩子吗?
此元素是否具有name类?
此元素是否具有值为data-foobar属性?
指针是否在此元素上?
这是div元素吗?


完全没有理由出于性能原因而强制执行此类命令。实际上,我认为通过优先选择某些简单选择器(无论它们在序列中的什么位置),可以提高性能。 (您还将注意到,没有考虑::after,这是因为伪元素不是简单的选择器,甚至从不输入匹配方程式。)

例如,众所周知,ID选择器是最快的。好吧,鲍里斯(Boris)在对链接问题的回答的最后一段中这样说:


  还要注意,浏览器已经做了其他优化,甚至可以避免匹配绝对不匹配的规则。例如,如果最右边的选择器具有一个ID,并且该ID与元素的ID不匹配,则在壁虎中根本不会尝试将该选择器与该元素进行匹配:尝试的“具有ID的选择器”集合来自对元素ID的哈希表查找。因此,仅考虑最右边选择器的标记/类/ ID,这就是70%的规则很有可能匹配,但仍然不匹配。


换句话说,是否具有如下所示的选择器:

div#foo.bar:first-child


或这个:

div.bar:first-child#foo


壁虎将始终先检查ID和类,而不管其在序列中的位置。如果该元素没有ID和与选择器匹配的类,则会立即将其丢弃。如果你问我,很快就可以了。

那只是壁虎为例。这在实现之间也可能有所不同(例如,Gecko和WebKit可能与Trident甚至Presto有所不同)。当然,有一些供应商普遍同意的策略和方法(首先检查ID可能没有区别),但是细节上可能有所不同。

关于css - 选择器引擎朝哪个方向准确读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37003201/

相关文章:

html - 我将如何使用 CSS 选择它?

html - <p> 标签脱离了它的 <div>

javascript - 在 html 中切换 View

php - 滚动留言板,如何链接到 div 中的 div 中的 id?

java - 英国航空网站是否实现网站预防自动化

javascript - 可选的 div 背景颜色

html - 为什么 CSS 后代无法识别?

javascript - 如何防止特定的 child 使用 Jquery 进行事件绑定(bind)?

css - Safari 4 格 :hover Support

twitter-bootstrap - :before pseudo-element when there is one class but NOT another class 的 CSS 选择器