高效渲染 CSS

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 $200 免费信用额度!

我承认自己并不经常考虑这个想法…… **我们编写的 CSS 在浏览器渲染速度方面有多高效?**

这绝对是浏览器供应商关注的事情(页面加载速度越快,使用他们产品的人就越高兴)。 Mozilla 有一篇文章 关于最佳实践。 Google 也一直在努力让网络更快。 他们也有一个 关于此的文章

让我们介绍一下他们提出的几个主要想法,然后讨论其实际应用。

从右到左

要理解浏览器如何读取 CSS 选择器,一个重要的事情是,它们从 **右到左** 读取。 这意味着在选择器ul > li a[title="home"]中,第一个被解释的是a[title="home"]。 这部分也被称为“关键选择器”,因为它最终是要被选择的元素。

ID 最高效,通用选择器效率最低

有四种关键选择器:ID、类、标签和通用。 它们的效率顺序也与之相同。

#main-navigation {   }      /* ID (Fastest) */
body.home #page-wrap {   }  /* ID */
.main-navigation {   }      /* Class */
ul li a.current {   }       /* Class *
ul {   }                    /* Tag */
ul li a {  }                /* Tag */
* {   }                     /* Universal (Slowest) */
#content [title='home']     /* Universal */

当我们将这个从右到左的想法,以及关键选择器想法结合起来时,我们可以看到这个选择器效率并不高

#main-nav > li {   }  /* Slower than it might seem */

虽然这感觉很奇怪,与直觉相悖…… 由于 ID 效率很高,我们认为浏览器应该可以很快找到这个 ID,然后很快找到 li 子节点。 但实际上,相对较慢的 li 标签选择器首先被执行。

不要标签限定

永远不要这样做

ul#main-navigation {  }

ID 是唯一的,因此它们不需要标签名称与其关联。 这样做会使选择器效率降低。

如果可以避免,也不要对类名进行标签限定。 类名不是唯一的,因此理论上你可以使用一个类名来做一些对多个不同元素都有用的事情。 如果你想根据元素的不同让样式不同,你可能需要标签限定(例如li.first),但这非常罕见,因此一般来说,不要这样做。

后代选择器效率最低

David Hyatt

后代选择器是 CSS 中效率最低的选择器。 它极其低效 - 尤其是如果选择器在标签或通用类别中。

换句话说,像这样的选择器是一个效率灾难

html body ul li a {  }

失败的选择器比匹配相同选择器的效率更高

我不确定我们能从中学到什么,因为如果你在 CSS 中有很多不匹配任何东西的选择器,那,嗯,相当奇怪。 但是值得注意的是,在选择器的从右到左解释中,一旦它匹配失败,它就会停止尝试,因此消耗的能量比需要继续解释要少。

考虑为什么你要写这个选择器

考虑一下

#main-navigation li a { font-family: Georgia, Serif; }

字体系列是级联的,所以你可能不需要一开始就写一个非常具体的选择器(如果你只是更改字体)。 这可能同样有效,而且效率更高

#main-navigation { font-family: Georgia, Serif; }

CSS3 和效率

来自 David Hyatt 的有点令人沮丧的消息

CSS3 选择器的悲惨真相是,如果你关心页面性能,实际上根本不应该使用它们。

整个 评论 值得一读。

CSS3 选择器(例如 :nth-child)在帮助我们定位想要的目标元素,同时保持标记简洁和语义化的方面非常棒。 但事实是,这些花哨的选择器在使用上更占用浏览器资源。

所以问题是,我们真的不应该使用它们吗? 让我们来思考一下其实际应用……

实际应用

我上面链接到的那篇 Mozilla 文章? 已经 10 年了。 事实:10 年前的计算机速度慢得多。 我感觉这些东西在当时更加重要。 10 年前我刚满 21 岁,我甚至不知道 CSS 是什么,所以我不会对你老派…… 但我感觉我们不怎么讨论渲染效率,是因为这已经不是什么大问题了。

我的感觉是这样的:我们上面讨论的最佳实践无论如何都是有意义的。 你不妨遵循它们,因为它们也不会限制你在 CSS 中的能力。 但你也不必死板地遵守它们。 如果你碰巧需要从网站中榨取每一滴性能,并且以前从未考虑过这些东西,那么你可能需要重新检查你的样式表,看看有哪些地方可以做得更好。 如果你在网站中没有看到渲染速度变慢,那么就不用担心,只需了解一下,以备将来之需。

超高速,零实用性

所以我们知道 ID 是效率最高的选择器。 如果你想创建一个渲染效率最高的页面,你实际上需要给页面上的每一个元素都赋予一个唯一的 ID,然后使用单个 ID 选择器来应用样式。 这会非常快,也很荒谬。 这很可能非常不语义化,而且难以维护。 即使是在以性能为重的网站上,你也很难看到这种做法。 **我认为这里需要注意的是,不要为了高效的 CSS 而牺牲语义化或可维护性。**

 

感谢 Jason Beaudoin 给我发邮件谈论这个想法。 如果有谁对这些东西更了解,或者你还有其他类似的技巧,请告诉我!

顺便说一句,我还想提一下,由于 CSS 样式选择器也用于许多 JavaScript 库,因此这些相同的概念也适用。 ID 选择器将是最快的,而复杂的限定后代选择器等则会更慢。