开头的废话
很久没发文章了,最近的经历并不那么愉快。过一段时间可能会写一篇非技术总结,以之自勉。
为什么会写Css选择器的文章?主要是最近工作遇到要封装基础样式,也有几个要求,其中一个是样式的权重要低。最开始我想得非常简单,仔细思考过后,发现自己对选择器的基础优先级还是比较了解的。但对于那些复杂的选择器优先级计算,自己并不是非常清晰。因此,就有这么一篇简单的小文章,给自己梳理一下。
1、基本的选择器类型
常见的选择器,大致有以下几种类型:
- ID选择器
- class选择器
- 属性选择器
- 伪类选择器
- 标签选择器
- 伪元素选择器
- 全局选择器
前面几种前端开发者都非常熟悉。稍微补充一下,什么是伪元素选择器(pseudo-elements)呢?刚听名字觉得很懵。实际也是很常用的东西,举个栗子——:before和:after。至于全局选择器其实就是*,代表任意元素。
2、基本的优先级关系
基本的优先级按照从高到低的关系,依次如下:
ID选择器 > class选择器、属性选择器、伪类选择器 > 标签选择器、伪元素选择器 > 全局选择器
为了方便描述,我将选择器按优先级,从高到低分为四个级别:
- 第一级:ID选择器
- 第二级:class选择器、属性选择器、伪类选择器
- 第三级:标签选择器、伪元素选择器
- 第四级:全局选择器
同一级别的选择器优先级相同。在选择器优先级相同的情况,主要看选择器在代码中的顺序。也就是说,多个优先级相同的选择器定义了相同的样式属性,顺序靠后的选择器中的样式生效。
其次,!important可以改变样式的优先级,将样式属性的优先级提升到最高。但这是针对具体的样式,而不是针对选择器的。
注意:实际上选择器并不存在级别这个概念,这里只是为了方便描述而已。
3、复杂的优先级计算
假设:
- 第一级选择器的数量为
a - 第二级选择器的数量为
b - 第三级选择器的数量为
c - 第四级选择器忽略
优先对比第一级选择器的数量,如果数量相同,再对比第二级选择器的数量,依次类推。如果数量全部相同,那么就看选择器在代码中的顺序。
举个栗子:
#id.a.b.c {} // {a=1, b=3, c=0}
#id.a.c {} // {a=1, b=2, c=0}
上述两个选择器的a值相等,继续对比b值。第一个选择器的b值大于第二个选择器的b值。因此,第一个选择器中的样式属性优先级更高。
4、错误的理解
有一种这样的说法,在计算选择器优先级时,第一级选择器的权重是100,第二级选择器的权重是10,第三级选择器的权重是1。大多数情况,这样理解也是没有什么问题。
但现在假设我定义1个ID选择器和11个class的复合选择器。按照上述的计算方法,ID选择器的权重是100,复合选择器的权重是110,因此复合选择器的优先级更高。
代码如下:
<body>
<p id="x" class="a b c d e f g h i j k">selector</p>
<style>
.a.b.c.d.e.f.g.h.i.j.k {
color: blue;
}
#x {
color: red;
}
</style>
</body>
测试结果是,字体颜色为红色。也就是说,即使11个class选择器组成的复合选择器,它的优先级仍然比ID选择器要低。因此,这种优先级计算方法并不准确。
5、特殊情况
:not选择器是一个否定类型的伪类选择器,:not选择器本身不参与选择器的数量计算,但被:not选择器所包含的选择器仍然会参与数量的计算。
代码如下:
<body style="color: black">
<p id="x">selector1</p>
<p class="a">selector2</p>
<style>
.a {
color: blue;
}
:not(#x) {
color: green;
}
</style>
</body>
测试结果是,第二个p标签中的文字是绿色,证明:not(#x)选择器的优先级高于.a选择器。
注意:有个细节的问题,body标签中定义了内联样式color: black。原因是:not选择器会匹配任何id不是x的元素,包括body元素和html元素。
6、子选择器和后代选择器
粗略的说,这两者的优先级其实是一样高的,代码如下:
<body>
<p class="a">selector</p>
<style>
body>.a {
color: red;
}
body .a {
color: blue;
}
</style>
</body>
测试结果是,p标签中的文字颜色跟这两个选择器在代码中的顺序有关。相邻选择器和兄弟选择器也是同样的道理。
7、推荐
如果大家想要查找一手资料,可以查看W3C Recommendation,本文很多内容也是参考此处。
推荐一个有趣的工具网站,可以用来测试选择器的优先级,链接如下。