mjy*_*mjy 10 css css-selectors css3 pagespeed
在尝试减少网页的HTML大小时,我遇到了谷歌和PageSpeed Firefox Add-On的建议,这些建议使CSS选择器的效率降低(几乎)让我重新考虑这些变化:
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; }
将导致a中的黑色文本<div id=foo>,但a)它不应该完成(需要W3C引用)和b)我不明白为什么它会导致对元素的简单O(1)检查明显变慢标签名称.
任何与现代浏览器源代码保持良好关系的人都可以对这些说法有所了解吗?由于大多数现代网站使用后代选择器(包括SO)并且它们具有明显的优势,我非常希望使用它们......
编辑:
我已经对生成的页面进行了一些实验,看起来浏览器对后代选择器的处理确实很可怜:
由(缩写)组成的页面:
#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> [...]
[前一行重复10000次]
(基本上是10000行,每行有50个嵌套的div,直到根节点和1个与10000匹配的选择器)
window.onload()使用Safari 5在2.2秒内加载和渲染(执行时间),使用Firefox 3.6.10只需不到10秒.
当.foo从非应用规则中删除类选择器时,使用Safari 5时页面大约需要200秒,使用Firefox 3.6.10需要96秒.这说明了后代选择器的实现有多糟糕(在这种情况下,10000规则中的每一个都可能导致遍历直到#top,其中规则失败).
儿童选择器的票价如何?#foo > span > div > div > div > div > div a {color: red;}(也永远不会匹配,但强制遍历6个父节点)Safari 5需要27秒,Firefox 3.6.10需要31秒.
结论
后代和儿童选择器目前都在主流浏览器上吮吸.如果您关心速度,至少对于非常常见的HTML标记(例如,img,div等),最好将丑陋的class/id属性添加到所有样式标记中.
看看Jonathan Snook最近的这篇文章:http://snook.ca/archives/html_and_css/css-parent-selectors
您将看到浏览器如何评估表达式以及为什么某些选择器效率低下的原因.
该帖子的相关引用:
CSS从右到左进行评估.
要确定CSS规则是否适用于特定元素,它将从规则的右侧开始,并以左侧的方式工作.
如果你有一个像body div#content p {color:#003366; 然后对于每个元素 - 当它被渲染到页面时 - 它首先会询问它是否是段落元素.如果是,它将在DOM上工作,并询问它是否是具有内容ID的div.如果它找到了它正在寻找的东西,它将继续向上移动到DOM,直到它到达身体.
通过从右向左工作,浏览器可以确定规则是否适用于它尝试以更快的速度绘制到视口的此特定元素.要确定哪个规则的性能更高或更低,您需要确定需要评估多少个节点以确定是否可以将样式应用于元素.