首页 文章

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

提问于
浏览
515

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

  • 这是为什么?

  • 这只是因为规范说的吗?

  • 如果从左到右进行评估,它会影响最终布局吗?

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

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


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

3 回答

  • 25

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

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

  • 19

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

    如果你只有一个选择器,只有一个元素可以与那个选择器进行比较,那么在某些情况下,从左到右更有意义 . 但这绝不是浏览器的情况 . 浏览器正在尝试呈现Gmail或其他任何内容,并且有一个 <span> 它没有使该数字上升 .

    特别是,在这种情况下,浏览器正在查看大多数选择器,它正在考虑与所讨论的元素不匹配 . 所以问题就变成了决定选择器没有匹配的问题 .

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

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

    所以浏览器从右边匹配;它提供了一个明显的起点,让您可以非常快速地摆脱大多数候选选择器 . 您可以在http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665看到一些数据(虽然这种表示法令人困惑),但结果是两年前特别是对于Gmail,对于70%的(规则,元素)对,您可以确定规则在之后不匹配检查规则最右边的选择器的tag / class / id部分 . Mozilla 's pageload performance test suite was 72%. So it'的相应数字确实值得尽可能快地摆脱所有规则中的2/3,然后只担心匹配剩余的1/3 .

    另请注意,浏览器已经做了其他优化,以避免尝试匹配明确赢得't match. For example, if the rightmost selector has an id and that id doesn't匹配元素's id, then there will be no attempt to match that selector against that element at all in Gecko: the set of 144770 that are attempted comes from a hashtable lookup on the element' ID的规则 . 因此,在考虑最右边的选择器的标签/类/ id之后,这是70%的具有很好匹配机会的规则仍然不匹配 .

  • 782

    从右到左解析,也称为 bottom-up parsing 实际上对浏览器有效 .

    考虑以下:

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

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

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

    需要注意的是 browser starts processing moment it gets a complete tag/node 并且不需要等待整个页面,除非它找到一个脚本,在这种情况下它暂时暂停并完成脚本的执行然后继续 .

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

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

相关问题