这篇文章已经在草稿箱里放了好久,考虑一下还是发布吧。这是翻译的文章,原文在这里Efficiently Rendering CSS
我们写的CSS有多高效?换个说法,浏览器渲染我们的CSS会有多快?我承认这个问题我考虑的不够多
这个问题本应该是浏览器厂商考虑的——他们的浏览器越快,用户就越喜欢用他们的产品。Mozilla有一篇关于这方面最佳实践的文章,一直坚持Web应该更快的Google也有一篇。
我们一起看看他们阐释的一些主要观点,然后探讨一下这些原则的实用价值
从右向左
浏览器如何读取你的CSS选择器?我们需要明白的最重要的一点是从右向左。比如这个选择器ul > li a[title="home"]
,浏览器首先读取的是a[title="home"]
。这个首先被读取的部分我们叫它key selector
,它是浏览器最終要选择的元素。
ID最快,Universal最慢
有四种类型的key selector
,解析速度由快到慢依次是:ID、class、tag和universal
#main-navigation { } /* ID(最快) */
body.home #page-wrap { } /* ID */
.main-navigation { } /* Class */
ul li a.current { } /* Class *
ul { } /* Tag */
ul li a { } /* Tag */
* { } /* Universal(慢) */
#content [title='home'] /* Universal */
我们把这个原则与从右向左结合来看,就会发现下面这个选择器并不是很快
#main-nav > li { } /* 比它看起来的要慢 */
这真有点违反我们的直觉。。。由于ID很快,我们直觉的以为浏览器会迅速的找到#main-nav
,然后找到它的孩子li
。但实际上,浏览器首先解析的是相对较慢的li
不要tag-qualify
永远不要这样做
ul#main-navigation { }
ID已经是唯一的,不需要Tag来标识,这样做会让选择器变慢。
如果你可以,也尽量不要在class上这样用。class不是唯一的,你可以用它来处理很多不同的元素。如果你希望拥有同一个class的元素有不同的样式,你可能需要tag-qualify(比如li.first
),但这是很少见的。
后代选择器最糟糕
David Hyatt这样说过
The descendant selector is the most expensive selector in CSS. It is dreadfully expensive — especially if the selector is in the Tag or Universal Category.
换句话说,下面这个选择器是很低效的
html body ul li a { }
匹配失败的选择器更高效
我不清楚从这里面我们可以学到什么,在自己的CSS文件里写很多没用的东西岂不是很奇怪。但还是应该说明一下,当从右向左的解析一个选择器时,如果没有匹配的結果,浏览器将会停止下一步的动作,于是更高效了。。。
想清楚你为什么这样写
考虑这样一个选择器
#main-navigation li a { font-family: Georgia, Serif; }
font-family
是可以级联的,所以你可能根本不需要如此特殊的一个选择器(如果你只是要改变字体的话)。这样做会更高效,而且是高效很多
#main-navigation { font-family: Georgia, Serif; }
CSS3的效率问题
David Hyatt的一些杯具说法:
The sad truth about CSS3 selectors is that they really shouldn’t be used at all if you care about page performance.
CSS3选择器(比如 :nth-child)能够漂亮的定位我们想要的元素,又能保证我们的CSS整洁易读。但是这些神奇的选择器会浪费很多的浏览器资源。
那该怎样做?我们真的不应该使用它们吗?让我们考虑一些实用的东西
实用性
记 得我在上面列出的Mozilla那篇文章吗?得有10年之久了。事实上,10年前的电脑是很慢的。我觉得这些在过去是很重要的东西。10年前我21岁,我 甚至不知道CSS是什么,囧,不知道怎么翻译。。。我觉得现在我们很少谈论CSS渲染的效率问题或许是因为这已经不再是个大问题了。
我是这样认为的:不管怎样,我们上面谈论的最佳实践都是有作用的。你可以遵守这些规则,因为他们并不会限制你CSS的能力。但也大可不必把它们当作教条执行。
如果你的网站正好非常缓慢,而你之前并没有考虑过这些CSS最佳实践,你可能需要好好检查一下你的CSS了。如果你的网站没有任何缓慢的迹象,那可以不用理它,以后写CSS时注意就好了。
极速却不实用
我 们知道了ID是最高效的选择器。如果你想要一个渲染最快的网页,那你可以给页面上每一个元素一个唯一的ID,然后样式化每一个ID。这将会超级快,但也是 极其滑稽的。这可能让你的CSS文件很难读很难维护。在一些对性能要求很高的硬编码的网站上你都很难看到这种写法。我们不应该为了效率而牺牲可读性和可维 护性。
感謝Jason Beaudoin告诉我这些想法。如果有人了解更多相关的东西,或者你需要补充些什么,那就告诉大家吧。
简单说一点,很多的JavaScript库都使用了CSS选择器,上面的原则也依然适用。ID是最快的,而复杂的后代选择器会比较慢。