【问题标题】:Efficient and inefficient CSS selectors (according to Google, PageSpeed ...)高效和低效的 CSS 选择器(根据 Google、PageSpeed ...)
【发布时间】:2011-04-26 21:30:06
【问题描述】:

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

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

具体来说,后代选择器非常适合使用 ID 或 CLASS 属性选择整个块(例如 DIV),然后使其所有子元素都没有 CLASS/ID 属性。但如果应用规则的遍历顺序如谷歌所述,则不应使用:

后代选择器效率低下,因为对于每个匹配键的元素,浏览器还必须遍历 DOM 树,评估每个祖先元素,直到找到匹配项或到达根元素。密钥越不具体,需要评估的节点数就越多。

我非常怀疑浏览器是否使用了如此低效的遍历顺序,当然它们只会处理与顶部选择器组件匹配的元素的子树,即在#foo span {...} 中,只有 #foo 以下的元素应该被检查,而不是每个跨度.任何看过最近浏览器代码的人都可以确认/否认这一点吗?

第二个有问题的建议是关于过度限定的选择器:

ID 选择器根据定义是唯一的。包含标签或类限定符只会添加需要评估的冗余信息。

如果 ID 选择器在定义上是唯一的,为什么浏览器需要检查冗余信息?我知道他们这样做是因为例如,

div#foo { 颜色:黑色; } #foo { 颜色:白色; }

将导致<div id=foo> 中出现黑色文本,但是 a) 它不应该完成(?需要 W3C 参考)和 b) 我不明白为什么它会导致一个简单的 O( 1) 检查元素的标签名称。

任何熟悉现代浏览器源代码的人都可以阐明这些说法吗?由于大多数现代网站都使用后代选择器(包括 SO)并且它们具有明显的优势,我非常想使用它们...

编辑:

我对生成的页面进行了一些实验,似乎浏览器对后代选择器的处理确实很可怜:

由(缩写)组成的页面:

#top a {text-decoration: none;}

#foo1 a.foo {颜色:红色;}

#foo2 a.foo {颜色:红色;}

[...重复 10000 次]

...[嵌套 50 次]bla
[...]

[上一行重复 10000 次]

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

使用 Safari 5 在 2.2 秒内加载和呈现(直到 window.onload() 执行的时间),使用 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 秒。

结论

后代选择器和子选择器目前在主流浏览器上都很糟糕。如果您关心速度,最好为所有样式标签添加丑陋的 class/id 属性,至少对于非常常见的 HTML 标签(如 a、img、div 等)。

【问题讨论】:

  • 2/5 似乎是 25%。有 2 个问题是用来举例的,没有一个比其他所有问题都更“正确”(选择一个是任意的),一个没有真正有用的答案(老实说)。
  • 关于没有例子的问题,你能解决你的问题吗?如果是这样,请发布您的解决方案并接受它作为答案(假设没有其他人类似)。

标签: css css-selectors pagespeed


【解决方案1】:

看看 Jonathan Snook 最近的这篇文章:http://snook.ca/archives/html_and_css/css-parent-selectors

您将看到浏览器如何评估表达式以及某些选择器效率低下的原因。

帖子中的相关引述:

CSS 从右到左进行评估。

判断一个CSS规则是否 适用于特定元素,它 从规则的右边开始,并且 向左工作。

如果你有像 body 这样的规则 div#content p { 颜色:#003366; } 然后 对于每个元素——当它被渲染时 到页面——它会首先询问它是否是 段落元素。如果是的话就会 沿着 DOM 向上工作并询问是否 它是一个带有内容 ID 的 div。如果 它会找到它正在寻找的东西,它会 继续向上 DOM 直到它 到达身体。

浏览器从右到左 可以确定规则是否适用 对于这个特定的元素,它是 试图在视口上画很多 快点。确定哪个规则是 或多或少的性能,你需要 弄清楚需要多少个节点 评估以确定样式是否 可以应用于元素。

【讨论】:

  • 感谢您的链接,虽然它没有提供任何证据表明浏览器现在确实这样做了,但它是另一个数据点。我不明白的是为什么浏览器会以如此低效的方式处理 DOM,例如在遍历文档时维护祖先节点 ID/类和适用 css 规则的运行列表,以避免使用后代(应该称为祖先?)选择器检查规则。它可能会简化 DOM 操作,但它必然会破坏现代、更漂亮/可读的 css 选择器用法、有用的 esp 的采用。对于白标网站...
  • Snook 在谷歌工作,是一位长期的网络大师,如果他这么说,我相信他的浏览器确实按照他说的那样处理 DOM。
猜你喜欢
  • 2013-04-05
  • 1970-01-01
  • 2013-07-27
  • 2011-04-18
  • 1970-01-01
  • 2011-07-03
  • 2014-06-24
  • 1970-01-01
  • 2011-11-25
相关资源
最近更新 更多