“使用高效的 CSS 选择器”规则发生了啥?

Posted

技术标签:

【中文标题】“使用高效的 CSS 选择器”规则发生了啥?【英文标题】:What happened to the "Use efficient CSS selectors" rule?“使用高效的 CSS 选择器”规则发生了什么? 【发布时间】:2014-10-26 09:48:32 【问题描述】:

Google PageSpeed 有一条建议要求网络开发者Use efficient CSS selectors

避免匹配大量 元素可以加速页面渲染。

详情

当浏览器解析 html 时,它会构建一个内部文档树 表示要显示的所有元素。然后匹配 元素到各种样式表中指定的样式,根据 标准 CSS 级联、继承和排序规则。在 Mozilla 的 实现(可能还有其他),对于每个元素, CSS 引擎通过样式规则搜索以找到匹配项。引擎 从右到左评估每个规则,从最右边开始 选择器(称为“键”)并在每个选择器中移动,直到它 找到匹配项或丢弃规则。 (“选择器”是文档 规则应适用的元素。)

根据这个系统,引擎必须评估的规则越少 更好。 [...]。之后,对于包含大量 元素和/或大量 CSS 规则,优化定义 规则本身也可以提高性能。关键是 优化规则在于定义与 可能并且避免不必要的冗余,以允许样式 无需花费时间评估规则即可快速找到匹配项的引擎 不适用。

此建议已从当前的 Page Speed Insights rules 中删除。现在我想知道为什么这条规则被删除了。与此同时,浏览器在匹配 CSS 规则方面是否变得高效?这个建议还有效吗?

【问题讨论】:

好,现在我们可以花时间编写 CSS 而不必担心浏览器性能了。 我看不出这是一个寻求异地资源的问题。问题是 关于 一个场外资源 - 它被引用在你身上。这看起来更像是一个没有非常具体或明确答案的问题,或者只有非常具体的人才能提供这样的答案。 【参考方案1】:

2011 年 2 月,Webkit 核心开发人员 Antti Koivisto made several improvements 向 Webkit 中的 CSS 选择器性能介绍。

Antti Koivisto 教 CSS 样式选择器跳过同级选择器和更快的排序,这带来了一些小的改进,之后他获得了两个更棒的补丁:一个启用祖先标识符过滤以构建树,将样式的剩余时间减半在典型的页面加载上进行匹配,并为简单的选择器提供了一条快速路径,可在某些网站上再加快 50% 的匹配速度。

CSS Selector Performance has changed! (For the better) 的 Nicole Sullivan 更详细地介绍了这些改进。总之——

根据 Antti 的说法,直接和间接相邻的组合器仍然很慢,但是,祖先过滤器和规则哈希可以降低影响,因为这些选择器很少会被匹配。他还说,webkit 仍有很大的空间来优化伪类和元素,但无论如何它们都比尝试使用 javascript 和 DOM 操作来做同样的事情要快得多。事实上,尽管仍有改进的空间,他说:

“适度使用,从风格匹配的角度来看,几乎所有东西都会表现得很好。”

虽然浏览器在匹配 CSS 选择器方面要快得多,但值得重申的是,仍应优化 CSS 选择器(例如,尽可能保持“平坦”)以减小文件大小并避免特异性问题。

【讨论】:

那是从 2011 年开始的,不知道现在的情况是什么(2015 年)。【参考方案2】:

这是thorough article(日期为 2014 年初)

我引用了 Benjamin Poulain,一位 WebKit 工程师,他对 CSS 选择器性能测试有很多话要说:

~10% 的时间花在光栅化器上。约 21% 的时间花费在 在第一个布局上。约 48% 的时间花在解析器和 DOM 上 树创建 ~8% 用于样式解析 ~5% 用于 收集风格——这是我们应该测试的,也是 应该花费大部分时间。 (剩下的时间分散在很多 很多小功能)

他继续说:

“我完全同意预先优化选择器是没有用的,但是 出于完全不同的原因:

实际上不可能预测最终的性能影响 通过仅检查选择器来对给定的选择器进行检查。在发动机中, 选择器被重新排序、拆分、收集和编译。要知道 给定选择器的最终性能,你必须知道 收集了选择器的哪个桶,它是如何编译的,以及 最后,DOM 树长什么样子。

所有这些在各种引擎之间都有很大的不同,使得 整个过程更难以预测。

我反对 Web 开发人员优化选择器的第二个论点 是他们可能会使事情变得更糟。大量的 关于选择器的错误信息大于正确的跨浏览器 信息。一个人做正确的事的机会很大 低。

在实践中,人们发现 CSS 的性能问题并开始 一项一项删除规则,直到问题消失。我认为那是 解决这个问题的正确方法,这很容易并且会导致正确 结果。”

有一些方法,例如BEM,可以尽可能扁平化地建模 CSS,以最大限度地减少 DOM 层次结构依赖性并解耦 Web 组件,以便它们可以在 DOM 中“移动”并且无论如何都可以工作。

【讨论】:

【参考方案3】:

也许是因为现在为 CMS 或框架做 CSS 更常见,而且很难避免使用通用的 CSS 选择器。这是为了限制样式表的复杂性。

此外,现代浏览器在呈现 CSS 方面非常快。即使在 IE9 上使用巨大的样式表,渲染也不觉得很慢。 (我必须承认我在一台好计算机上进行了测试。也许那里有基准测试)。

无论如何,我认为你必须编写非常低效的 CSS 来减慢 Chrome 或 Firefox 的速度......

有一个 2 年前的关于性能的帖子 @Which CSS selectors or rules can significantly affect front-end layout / rendering performance in the real world?

我喜欢他的单行结论:在“是的,这个 CSS 有意义”范围内的任何事情都可以。

【讨论】:

Manuszep -- 实际上检测和测量由于 CSS 选择器而导致的页面加载/页面渲染速度下降并不常见。最坏的情况是您有许多单独加载的 CSS 文档并且您正在感知网络延迟。 如果你写了很多糟糕的 CSS 选择器并通过 jQuery (Sizzle) 选择器引擎使用它们,你可能会遇到这种减速,该引擎使用 JavaScript 解释选择器,然后在整个文档中搜索元素. 注意:大多数新浏览器现在都实现了“本机”选择器解析器和提取器,它们公开了浏览器自己的实现,这意味着 JavaScript 引擎不再负责这部分计算。 @Mihai Stancu:你是说最初的 CSS 实现用 JavaScript 编写的?我觉得很难相信。阿特伍德定律直到他放下它才开始生效。 @BoltClock -- 我没说过这样的话。我说过,即使你写了很多糟糕的 CSS 选择器,你也不会觉得速度慢……除非这些选择器不是用于 CSS 样式,而是用于 jQuery 中的元素选择(嘶嘶声)。

以上是关于“使用高效的 CSS 选择器”规则发生了啥?的主要内容,如果未能解决你的问题,请参考以下文章

2019.12.21---今天学了啥?

XPathReader 发生了啥

QTableView 的 HTML 渲染器 - 字体大小发生了啥变化?

在 sql server 2012 中为西班牙语选择了啥排序规则?

Angular2:配对选择器在@Directive中做了啥

jQuery 类选择器和单击事件,我错过了啥吗?