css小课堂:选择符

本文探讨了CSS选择符对于代码质量和性能的影响,指出良好的CSS应兼顾开发人员和浏览器的友好性。文章强调了关键选择符的重要性,提倡使用更具体的选择符以减少浏览器匹配负担,提高样式匹配速度。建议使用类选择符,避免过度使用ID和链式选择符,并优化选择符序列长度,以提高代码的可维护性和性能。同时,要注意选择符的合理使用以避免不必要的复杂性,确保代码的可读性和重用性。
摘要由CSDN通过智能技术生成

当我第一次编写 css时,代码的高度自由度一直让我感到困惑。也就是说,同样的设计,如果让不同的人去执行,最终的代码肯定会有所不同。但是这也有个问题,如果不同的人用不同的方法和代码风格,实现相同的设计,那么就很难判断谁做得更好。想想看,既然所有的设计都实现了,达到了目的, css这种没有程序逻辑的代码,又能找出什么能说明谁做得更好?

现在,我的观点是, css这一描述性语言,在代码质量方面,仍有评判的余地。判断标准是可维护性(Maintainability)和性能(Performance),用更通俗的话讲,好的 css既有利于开发人员的工作(dev-friendly),也有利于浏览器(browser-friendly)。这篇文章展示了如何从 css选择符的角度改进 css代码质量。

重点选择符与浏览器样式规则匹配原则

在以前的初学者中, css选择符的概念也曾在 css优先级的开始部分被提及,它是指每个样式规则中,一个描述样式作用于或{}之前的元素部分。这篇文章中,还将介绍另外一个概念:关键选择符(Key selector)。关键性的选择选择符是从每个样式规则开始的{之前的最后一个选择符,如下图:

css选择符会决定后面的属性定义要对哪些元素起作用,因此存在一个浏览器匹配程序,该程序基于 css选择符应用样式到相应的元素。David Hyatt在 Writing Efficient CSS for use in the Mozilla UI一文中提到浏览器的样式匹配系统:

The style system matches a rule by starting with the rightmost selector and moving to the left through the rule’s selectors. As long as your little subtree continues to check out, the style system will continue moving to the left until it either matches the rule or bails out because of a mismatch.

也就是说,当样式匹配时,浏览器引擎按照从右到左的顺序执行。当特定地匹配某个样式规则时,这个从右到左的过程继续进行,直到整个选择符序列读完并完成匹配为止,或者由于某个地方的不匹配而被取消(然后转到另一个样式规则)。

关于浏览器为何选择这种匹配顺序,您可以参考 StackOverflow上的相关讨论。大概解释一下,因为最右边的关键选择符直接表示样式定义应该对哪个元素起作用,因此从右到左的顺序更有利于浏览器在初始匹配时确定具有样式定义的元素集合,并且在找到某个元素的样式时,可以更快地避开大多数实际上不起作用的选择符。

css选择符更好,它可以让浏览器在样式匹配期间减少匹配查询的次数,以更快的速度完成样式匹配,从而优化前端性能。在这里,您还必须参考浏览器从右到左匹配样式的顺序。

正确地使用 css选择符更为具体

更为特定的关键选择选择符

当进行样式匹配时,浏览器引擎首先读取关键选择符,因此,如果您在某个样式规则中使用更为特殊和具体的选择符,将有助于减少浏览器的查找匹配数。

例如下面这类选择符:

1

Content. note span {}

后一个 span是关键的选择符,而 span这个标签,在网页中用得很多。由于从 span开始读取选择符,浏览器可能会在样式匹配方面做一些额外的工作。

如果您确定只需要为特定的 span元素定义样式,那么最好将 class命名为 span,例如命名为span.note_text,然后简单写为:

1

.note_text {}

利用类选择符

类选择符(class选择符)是性能优化的最佳选择符。ID与 class相比的缺点是,它只允许为一个元素定义,并且不能重用。而且,在使用方面, class并不比 class好。在许多情况下,要确定某个元素是否是惟一的非常困难。此外,使用 class定义样式,同时将 ID保留给 javascript也是一种很好的做法。尽可能的话,不要使用 ID定义样式。

与 class相比, html中标签的重复性更强,所以当进行样式匹配时,浏览器同样可以做更多的工作。可能的话,除了 css样式清零(reset)之外,没有使用 tableselect (也叫元素选择符)。

压缩选择符序列

在 css中,继承写法(准确地说是指 css关系选择符中的包含选择符)是一种常用的写法。如果两个元素都具有相同的标签或者使用相同的 class名称,那么从父元素添加一个选择符来组成一个选择符序列,就可以避免两个元素的样式相互影响而不需要它们。例如,.confirm_layer.submit_btn表示, class的名称为submit_btn,而 class的父元素为confirm_layer,则应用该样式。

然而,避免元素样式的交互作用并不表示继承选择符的任意使用。如前所述,浏览器从右到左读取整系列的选择符,直到读完并完成匹配,或者因为不匹配而取消。所以选择符序列短更有利于浏览器更快地完成匹配过程。冗长的选择符相对序列会被视为无效,例如:

1

.header ul li .nav_link{}

推荐如下:

1

nav_link {}. header

一般而言,继承级不超过3层,才能满足实际的开发需求。所以,应该通过使用较短的选择符序列来减少不必要的继承层次。

另外,更长的序列选择符也有问题。样式规则具有更长的选择符,对 css优先级的计算值也比较大,因此,如果以后需要写新的样式来覆盖选择符(或使用 ID),则需要写更长的选择符(或使用 ID)以提高 css优先级。这样既影响性能,又影响代码可读性。

不要使用链式选择符

链接选择符(Chaining selectors)是一种将多个选择符同时写入一个元素的情况。例如,p.na me是指 class名为 name并且标签是 p的元素,用于应用样式。判断性组合可以是 ID选择符、标签选择符、类选择符的任意组合。

然而,链接选择符被过度定义(over qualified),这对重用和性能优化都没有好处。例如:

1

a# author {}

推荐如下:

1

#作者{}

这儿不需要 a了。标识符只对应于一个元素,因此不再需要强调该元素的标签(因此, class也不必)。还有其他

1

. contentspan.ar row {

推荐如下:

1

arrow {}. content

在span.ar row中使用 span也没有必要。首先,这增加了样式匹配时浏览器的额外工作:检查 class名为 arrow的元素的标签名是否为 span,从而降低性能。从另一个方面来说,如果去掉了. arrow的样式定义,那么它可以用于更多的元素,并且具有更好的重用性。不然的话,还是要告诉其他人,这个时候只能用在 span标签上。

与之类似,多个类的链接方式,例如

1

succuss {}. tips

推荐修改名称,写入:

1

_ succuss { www.bmc8888.com }

这有助于减少浏览器中其他样式匹配操作。

另外,IE6中也有一个问题,就是当多个 class选择符写在一起时,比如.class1.class2.cl ass 3,通常情况下,样式只适用于所有 class都包含的元素。但是IE6只承认最后一个符合.class3选择符的元素应用样式。

特殊情况

上述关于选择符编写的建议,仅仅是从浏览器渲染性能优化和代码重用性两个方面分析得出的理论结果。实际上,你不一定要严格按照这些方法去做。举例来说,如果您确实准备将 class中名为 intro的元素中的所有 a标签元素都添加到某个样式中,那么像. intro a这样的选择符是明智的。

结论

您也可以阅读 google developer中的 Use efficientCSS selectors,了解如何使用有效的 css选择符。

现在,现代浏览器在风格匹配方面也逐渐进行了更多的优化(参考 CSS Selector性能 haschanged!),其中一些内容我们已经不用再担心了。然而,这并不意味着无需考虑编写合理的 css选择符。仍然需要对 css选择符进行性能优化,您的选择符应该更好地体现您的意图,而非随意使用。更有甚者,用这样一个略微复杂的、经过深思熟虑的思想来编写 css选择符并不难。如果你愿意,养成这样的习惯,你会很自然地在这方面做得更好,何乐而不为?

上述就是本文的全部内容,希望对您有所帮助,也希望您能支持脚本之家的工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值