高效和低效的CSS选择器(根据Google,PageSpeed ...) [英] Efficient and inefficient CSS selectors (according to Google, PageSpeed ...)

查看:182
本文介绍了高效和低效的CSS选择器(根据Google,PageSpeed ...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试减少网页的HTML大小时,我遇到了Google提供的建议以及CSS选择器的PageSpeed Firefox Add-On注册效率(几乎)让我重新考虑这些更改:



http://code.google.com/intl/de-DE/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors



具体,后代选择器很适合使用ID或CLASS属性选择整个块(例如DIV),然后保持其所有子元素不含CLASS / ID属性。但如果应用规则的遍历顺序是由Google描述的,则不应使用它们:


后代选择器效率低,对于匹配键的每个元素,浏览器还必须遍历DOM树,评估每个祖先元素,直到找到匹配或到达根元素。


我非常怀疑浏览器使用这样一个无效的遍历顺序,肯定他们只会处理匹配顶部选择器组件的子元素,即 #foo span {...} 只有下面的元素#foo应该检查,而不是每一个跨度。谁能看到最近的浏览器代码确认/拒绝这个?



第二个有问题的建议是关于合格的选择器:


ID选择器根据定义是唯一的。


如果ID选择器根据定义是唯一的,为什么会有浏览器需要检查冗余信息?我知道他们是因为例如


div#foo {color:black; }
#foo {color:white; }


会在< div id = foo> ,但是a)它不应该完成(需要W3C引用)和b)我不明白为什么当它导致一个简单的O(1)检查元素的标签名称会明显减慢。



任何拥有现代浏览器源代码的用户都能对这些声明有所了解吗?由于大多数现代网站使用后代选择器(包括SO),他们有明显的优势,我非常想使用它们...



编辑: / b>



我已经尝试了一些生成的页面,看起来浏览器处理后代选择器确实可怜:



包含(缩写)的页面:


#top a {text-decoration:none;}

#foo1 a.foo {color:red;}



#foo2 a.foo {color:red;}



[...重复10000次]



< body id = top>



< div> ... [嵌套50次]< a href = foo> bla< / a>< / div> [...]
$ b

[上一行重复10000次]


(基本上是10000行,每行50个嵌套div直到根节点和1个匹配超出10000的选择器)



加载并渲染( window.onload()

.foo 时,使用Safari 5在2.2秒内执行$ c>类选择器从非应用规则中删除,该页面大约200秒与Safari 5和96秒与Firefox 3.6.10。这说明后代选择器的实现有多糟糕(在这种情况下,10000个规则中的每一个都可能导致直到#top的遍历,其中规则失败)。



如何儿童选择器票价? #foo> span> div> div> div> div> div a {color:red;} (也不会匹配但强制遍历6个父节点) Safari 5和31秒,Firefox 3.6.10。



结尾



和子选择器都吸引主要的浏览器。如果你关心速度,至少对于非常常见的HTML标签(如a,img,div等),最好将丑陋的类/ id属性添加到所有的样式标签中。

解决方案

查看Jonathan Snook最近发布的帖子: http://snook.ca/archives/html_and_css/css-parent-selectors



您将看到浏览器如何评估表达式



相关报价:


CSS从右到左计算。



要确定CSS规则
是否适用于特定元素,它



如果你有一个像body这样的规则
div#content p {color:#003366; }然后
为每个元素 - 因为它得到的
到页面 - 它首先问是否是一个
段落元素。如果是,它将
工作在DOM的方式,并询问是否
它是一个div与内容的ID。如果
找到它正在寻找的东西,它将
继续向上的DOM,直到
到达身体。



通过从右到左工作,浏览器
可以确定规则是否应用
到这个特定元素,它是
试图绘制到视口很快
。为了确定哪个规则是
或多或少的性能,你需要
计算需要多少个节点
来评估一个样式
是否可以应用到一个元素。



While trying to reduce the HTML size of a web page, I've come across suggestions by Google and the PageSpeed Firefox Add-On regading efficiency of CSS selectors that (almost) made me reconsider the changes:

http://code.google.com/intl/de-DE/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors

Specifically, descendant selectors are great for selecting a whole block (e.g. DIV) using an ID or CLASS attribute and then keeping all of its child elements free of CLASS/ID attributes. But if the order of traversal for applying the rules is as described by Google, they should not be used:

Descendant selectors are inefficient because, for each element that matches the key, the browser must also traverse up the DOM tree, evaluating every ancestor element until it finds a match or reaches the root element. The less specific the key, the greater the number of nodes that need to be evaluated.

I very much doubt that browsers use such an inefficient order of traversal, surely they would only process subtrees of elements that match the top selector component, i.e. in #foo span {...} only elements below #foo should be checked and not every single span. Can anyone who has looked at recent browser code confirm/deny this?

The second questionable suggestion is about overly qualified selectors:

ID selectors are unique by definition. Including tag or class qualifiers just adds redundant information that needs to be evaluated needlessly.

If ID selectors are unique by definition, why would browsers need to check the redundant information? I know that they do because for example,

div#foo { color: black; } #foo { color: white; }

will result in black text in a <div id=foo>, but a) it should not be done(? W3C reference needed) and b) I don't see why it would be noticeably slower when it results in a simple O(1) check of the element's tag name.

Can anyone on good terms with modern browsers' source code shed some light on these claims? Since most modern sites use descendant selectors (including SO) and they have clear advantages, I'd very much like to use them...

Edit:

I've experimented a bit with generated pages and it seems that the browsers' handling of descendant selectors is indeed pitiful:

A page consisting of (abbreviated):

#top a {text-decoration: none;}

#foo1 a.foo {color: red;}

#foo2 a.foo {color: red;}

[... repeated 10000 times]

<body id=top>

<div>...[nested 50 times]<a href=foo>bla</a></div>[...]

[previous line repeated 10000 times]

(basically 10000 lines with 50 nested divs each to traverse till the root node and 1 selector that matches out of 10000)

loads and renders (time till window.onload() executes) in 2.2 seconds using Safari 5 and just under 10 seconds with Firefox 3.6.10.

When the .foo class selector is removed from the non-applying rules, the page takes around 200 seconds with Safari 5 and 96 seconds with Firefox 3.6.10. This illustrates how badly the descendant selectors are implemented (in that case, each of the 10000 rules probably causes a traversal till #top, where the rule fails).

How do child selectors fare? #foo > span > div > div > div > div > div a {color: red;} (also never matches but forces traversal of 6 parent nodes) takes 27 seconds with Safari 5 and 31 seconds with Firefox 3.6.10.

Conclusion

Descendant and child selectors both suck currently on major browsers. It's still better to add ugly class/id attributes to all your styled tags if you care about speed, at least for very common HTML tags (such as a, img, div etc.).

解决方案

Have a look at this recent post by Jonathan Snook: http://snook.ca/archives/html_and_css/css-parent-selectors

You'll see how browsers evaluate expressions and the reasoning behind why certain selectors are inefficient.

A relevant quote from the post:

CSS gets evaluated from right to left.

To determine whether a CSS rule applies to a particular element, it starts from the right of the rule and works it's way left.

If you have a rule like body div#content p { color: #003366; } then for every element—as it gets rendered to the page—it'll first ask if it's a paragraph element. If it is, it'll work its way up the DOM and ask if it's a div with an ID of content. If it finds what it's looking for, it'll continue its way up the DOM until it reaches the body.

By working right to left, the browser can determine whether a rule applies to this particular element that it is trying to paint to the viewport much faster. To determine which rule is more or less performant, you need to figure out how many nodes need to be evaluated to determine whether a style can be applied to an element.

这篇关于高效和低效的CSS选择器(根据Google,PageSpeed ...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆