如何编写有效率的CSS选择器(CSS Selector)

0

搞效率的CSS选择器(Selector)不是一个新的主题,对于网页设计师而言,知道如何撰写CSS,是一个基本的技术能力,而了解如何撰写高效率的CSS则能让网页设计师的CSS作品获得更好的品质。

注意:这里所指的不是让开发者很有效率的写CSS,而是让开发者写出来的CSS Selector能很有效率的被浏览器执行。

本篇描述的规则,比较适用于非常需要全面提升「速度」的网站,像是每个页面的DOM元素都超过1000个以上的网站。如果是像我这种小小的博客,提升的效率就完全不明显,但身为专业的网页设计师,你还是必须把这些规则放在心上。

CSS 选择器(Selectors)

CSS 选择器你应该不陌生,我们可以透过基本的选择器去指定要处理的DOM元素,像是指定标签(div,span,body…)、ID(#header)、Class(.post)等选择器。

还有一些较不常见的伪类(pseudo-classes),如 :hover,或更为复杂的CSS3及regex选择器,如 :first-child或 [class^=”grid-“] 表示挑出所有类别名称以grid-为开头的元素。

而根据网站效率专家 Steve Souders 指出,各种CSS选择器的效率由高至低排序如下:

1. ID (#id)
2. Class (.class)
3. Type (即HTML标签,如div)
4. 邻接选择器 (如: h2+p,仅作用于邻接h2的p元素)
5. Child (如: li>ul)
6. Descendant (如:ul a)
7. Universal (*)
8. 属性 (如: [type=”text”])
9. 摸拟类别/元素 (如: a:hover)

值得注意的是,虽然ID在技术性上来说比较快,但差异其实很微小。在Windows上的Firefox6上测试,ID的reflow速度还比Class慢。但两者间reflow速度的差距根本不值一提。

注1:reflow是指css在为网页加上样式的过程之一。整个CSS绘制过程会先建立DOM,再进行reflow来确定各元素的位置,最于再进行绘制(render)样式的动作。这里有个reflow Mozilla官网的过程影片

注2:测试方式是用Steve Sounders制作的工具:css-selectors

复合选择器

你还可以用像是#nav a这种复合(combining)多个选择器的选择器,它的意思是「找到所有在ID为nav的元素下的a元素」。我们以自然语言的阅读方式,来阅读这种复合选择器的方式,通常就是这样用「由左至右」的方式来读,但是浏览器不是这样读的,浏览器是用「由右至左」的方式来理解选择器规则的。

这是为了效率而设计的读取方式,理由可参考这个讨论。于是,浏览器就从DOM树的上至下开始它的剖析查找旅程。

关键选择器 (key selector)

关键选择器就是最靠复合选择器右边的选择器,例如:#nav a,关键选择器就是a,它就是浏览器第一个寻找的规则。是的,浏览器会先找出所有的a元素,还记得上面我们刚讨论过的效率排行吗?此时就是该选择器效率表现的时刻。找出所有的a元素于,接着它会回头去看DOM树,去找看是否有a元素是住在ID为nav的元素之中。

因此,以下的选择器查找规则,就不是非常有效率:

#content *{}

这样的选择器会先找出「所有」页面上的元素,接着再找是否有任何元素是位于#content底下的。如此的查找成本非常昂贵。

所以,运用这样的知识,我们可以为订定CSS样式做出更好的决策。想像一下,如果你有一个充满大量资料的网页,而你是一个超级大站。在如此页面里,有成千上百个a元素。里头有一小块区域的连结,是专门留给社群连结的区块,它们都放在ID为social的ul元素里,假设里面有Twitter、Facebook、Google+等连结。因此,在这个页面里,我们共有三个社群连结,和其他成千上百个连结。

在这样的页面里,使用以下这个选择器,毫无疑问是非常没有效率的表示法:

#social a{}

如果要改善这个表示法,我们可以为#social里头的a,加上特定的class,例如:.social-link。但只标上 .social-link 似乎有点违背准确运用CSS类别的好习惯,因为这看来没什么意义,要达成折衷用法,我们可以这样写:

<!-- 略 -->
<ul id="social">
    <li><a href="#" class="social-link twitter">Twitter</a></li>
    <li><a href="#" class="social-link facebook">Facebook</a></li>
    <li><a href="#" class="social-link gplus">Google+</a></li>
</ul>
<!-- 略 -->

因此,我们的选择器就可以改成:

#social .social-link{}

这个新的选择器将比对「远低于」先前所需比对的元素,这表示浏览器就可以快速的找到目标元素,并且快速的完成样式的绘制。

过份限制的选择器

接着我们进一步来看其他的最佳化建议。这是一个「过份限制」的选择器例子:

html body .wrapper #content a{}

这是一个典型限定过了头的选择器例子,其中至少有三个元素是多余的,拿掉于剩下:

#content a{}

这表示,在浏览器查找到#content于,不用再进一步去找.wrapper、body和html,因为#content是唯一的,找到#content于,其于的查找都是多余的。

再看一个例子:

ul#nav li a{}

就可改成:

#nav a{}

知道这样的规则于,你就不会再轻易的写出像下面这种看来很炫,但却没啥效率的表示式了:

div:nth-of-type(3) ul:last-child li:nth-of-type(odd) *{ font-weight:bold }

另外,jQuery所支持的CSS Selector,读取方式也是从右至左的。

参考文章 http://www.mrmu.com.tw/2011/10/11/writing-efficient-css-selectors/

发表评论

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 必填字段 *

为何看不到我发布的评论?

正在提交, 请稍候...