Html 为什么浏览器从右到左匹配 CSS 选择器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5797014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do browsers match CSS selectors from right to left?
提问by tgandrews
CSS Selectors are matched by browser engines from right to left. So they first find the children and then check their parents to see if they match the rest of the parts of the rule.
CSS 选择器由浏览器引擎从右到左匹配。所以他们首先找到孩子,然后检查他们的父母,看看他们是否符合规则的其余部分。
- Why is this?
- Is it just because the spec says?
- Does it affect the eventual layout if it was evaluated from left to right?
- 为什么是这样?
- 仅仅是因为规范说吗?
- 如果从左到右评估它会影响最终的布局吗?
To me the simplest way to do it would be use the selectors with the least number of elements. So IDs first (as they should only return 1 element). Then maybe classes or an element that has the fewest number of nodes — e.g. there may only be one span on the page so go directly to that node with any rule that references a span.
对我来说,最简单的方法是使用元素数量最少的选择器。所以首先是 ID(因为它们应该只返回 1 个元素)。然后可能是具有最少节点数的类或元素——例如,页面上可能只有一个跨度,因此可以使用任何引用跨度的规则直接转到该节点。
Here are some links backing up my claims
这里有一些链接支持我的主张
- http://code.google.com/speed/page-speed/docs/rendering.html
- https://developer.mozilla.org/en/Writing_Efficient_CSS
- http://code.google.com/speed/page-speed/docs/rendering.html
- https://developer.mozilla.org/en/Writing_Efficient_CSS
It sounds like that it is done this way to avoid having to look at all the children of parent (which could be many) rather than all the parents of a child which must be one. Even if the DOM is deep it would only look at one node per level rather than multiple in the RTL matching. Is it easier/faster to evaluate CSS selectors LTR or RTL?
听起来这样做是为了避免必须查看父母的所有孩子(可能有很多),而不是必须是一个孩子的所有父母。即使 DOM 很深,它也只会在每个级别查看一个节点,而不是在 RTL 匹配中查看多个节点。评估 CSS 选择器 LTR 或 RTL 是否更容易/更快?
回答by Boris Zbarsky
Keep in mind that when a browser is doing selector matching it has one element (the one it's trying to determine style for) and all your rules and their selectors and it needs to find which rules match the element. This is different from the usual jQuery thing, say, where you only have one selector and you need to find all the elements that match that selector.
请记住,当浏览器进行选择器匹配时,它有一个元素(它试图确定样式的那个)和所有规则及其选择器,它需要找到哪些规则与元素匹配。这与通常的 jQuery 事情不同,例如,您只有一个选择器,并且需要找到与该选择器匹配的所有元素。
If you only had one selector and only one element to compare against that selector, then left-to-right makes more sense in some cases. But that's decidedly notthe browser's situation. The browser is trying to render Gmail or whatever and has the one <span>
it's trying to style and the 10,000+ rules Gmail puts in its stylesheet (I'm not making that number up).
如果您只有一个选择器并且只有一个元素可以与该选择器进行比较,那么在某些情况下从左到右更有意义。但这绝对不是浏览器的情况。浏览器正在尝试呈现 Gmail 或其他任何东西,并且具有<span>
它试图设置样式的内容以及 Gmail 在其样式表中放置的 10,000 多条规则(我不是在编造这个数字)。
In particular, in the situation the browser is looking at most of the selectors it's considering don'tmatch the element in question. So the problem becomes one of deciding that a selector doesn't match as fast as possible; if that requires a bit of extra work in the cases that do match you still win due to all the work you save in the cases that don't match.
特别是,在浏览器查看它所考虑的大多数选择器与相关元素不匹配的情况下。所以问题变成了决定选择器不尽快匹配的问题之一;如果在匹配的情况下需要一些额外的工作,您仍然会获胜,因为您在不匹配的情况下保存了所有工作。
If you start by just matching the rightmost part of the selector against your element, then chances are it won't match and you're done. If it does match, you have to do more work, but only proportional to your tree depth, which is not that big in most cases.
如果您开始时只是将选择器的最右边部分与您的元素进行匹配,那么很可能它不会匹配而您就大功告成了。如果它匹配,你必须做更多的工作,但只与你的树深度成正比,在大多数情况下这不是那么大。
On the other hand, if you start by matching the leftmost part of the selector... what do you match it against? You have to start walking the DOM, looking for nodes that might match it. Just discovering that there's nothing matching that leftmost part might take a while.
另一方面,如果您从匹配选择器的最左边部分开始……您将它与什么匹配?您必须开始遍历 DOM,寻找可能与之匹配的节点。只是发现最左边的部分没有匹配的东西可能需要一段时间。
So browsers match from the right; it gives an obvious starting point and lets you get rid of most of the candidate selectors very quickly. You can see some data at http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665(though the notation is confusing), but the upshot is that for Gmail in particular two years ago, for 70% of the (rule, element) pairs you could decide that the rule does not match after just examining the tag/class/id parts of the rightmost selector for the rule. The corresponding number for Mozilla's pageload performance test suite was 72%. So it's really worth trying to get rid of those 2/3 of all rules as fast as you can and then only worry about matching the remaining 1/3.
所以浏览器从右边匹配;它提供了一个明显的起点,让您可以非常快速地摆脱大多数候选选择器。您可以在http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665 上看到一些数据(尽管符号令人困惑),但结果是特别适用于 Gmail两年前,对于 70% 的 (rule, element) 对,您可以在检查规则最右侧选择器的 tag/class/id 部分后确定规则不匹配。Mozilla 页面加载性能测试套件的相应数字是 72%。因此,尝试尽快摆脱所有规则中的 2/3,然后只担心匹配剩余的 1/3,确实值得。
Note also that there are other optimizations browsers already do to avoid even trying to match rules that definitely won't match. For example, if the rightmost selector has an id and that id doesn't match the element's id, then there will be no attempt to match that selector against that element at all in Gecko: the set of "selectors with IDs" that are attempted comes from a hashtable lookup on the element's ID. So this is 70% of the rules which have a pretty good chance of matching that stilldon't match after considering just the tag/class/id of the rightmost selector.
另请注意,浏览器已经进行了其他优化,以避免尝试匹配肯定不会匹配的规则。例如,如果最右边的选择器有一个 id 并且该 id 与元素的 id 不匹配,那么在 Gecko 中根本不会尝试将该选择器与该元素匹配:尝试的“带有 ID 的选择器”的集合来自对元素 ID 的哈希表查找。所以这是 70% 的规则有很好的匹配机会,但在仅考虑最右边选择器的标签/类/ID 后仍然不匹配。
回答by aWebDeveloper
Right to left parsing, also called as bottom-up parsingis actually efficient for the browser.
从右到左解析,也称为自底向上解析,实际上对浏览器来说是高效的。
Consider the following:
考虑以下:
#menu ul li a { color: #00f; }
The browser first checks for a
, then li
, then ul
, and then #menu
.
该浏览器首先检查a
,然后li
,然后ul
,然后#menu
。
This is because as the browser is scanning the page it just needs to look at the current element/node and all the previous nodes/elements that it has scanned.
这是因为当浏览器扫描页面时,它只需要查看当前元素/节点以及它扫描过的所有先前节点/元素。
The thing to note is that the browser starts processing moment it gets a complete tag/nodeand needn't have to wait for the whole page except when it finds a script, in which case it temporarily pauses and completes execution of the script and then goes forward.
需要注意的是,浏览器在获得完整标签/节点的那一刻开始处理,不需要等待整个页面,除非找到脚本,在这种情况下,它会暂时暂停并完成脚本的执行,然后前进。
If it does the other way round it will be inefficient because the browser found the element it was scanning on the first check, but was then forced to continue looking through the document for all the additional selectors. For this the browser needs to have the entire html and may need to scan the whole page before it starts css painting.
如果反其道而行之,它将是低效的,因为浏览器在第一次检查时找到了它正在扫描的元素,但随后被迫继续浏览文档以查找所有其他选择器。为此,浏览器需要拥有整个 html,并且可能需要在开始 css 绘制之前扫描整个页面。
This is contrary to how most libs parse dom. There the dom is constructed and it doesn't need to scan the entire page just find the first element and then go on matching others inside it .
这与大多数库解析 dom 的方式相反。在那里构造了 dom,它不需要扫描整个页面,只需找到第一个元素,然后继续匹配其中的其他元素。
回答by Gregory A Beamer
It allows for cascading from the more specific to the less specific. It also allows a short circuit in application. If the more specific rule applies in all aspects that the parent rule applies to, all parent rules are ignored. If there are other bits in the parent, they are applied.
它允许从更具体的到不太具体的级联。它还允许在应用中短路。如果更具体的规则适用于父规则适用的所有方面,则忽略所有父规则。如果父级中还有其他位,则应用它们。
If you went the other way around, you would format according to parent and then overwrite every time the child has something different. In the long run, this is a lot more work than ignoring items in rules that are already taken care of.
如果你反过来,你会根据父母格式化,然后每次孩子有不同的东西时覆盖。从长远来看,这比忽略已经处理的规则中的项目要多得多。