Specificity 用于决定那一条 CSS 属性和一个元素最相关,并将该属性应用到该元素上。Specificity 基于匹配规则进行计算,匹配规则由一系列 CSS 选择器合成。
一个例子
下面首先通过一个例子来说明 Specificity 的使用方式。假设有如下的 html 文档:
1 | <div id="test"> |
和下面的 CSS 文档:
1 | div#test span { color: green; } |
下面直接给出不同匹配规则对应的 Specificity 值:
1 | div#test span { color: green; } /* 0-1-0-2 */ |
此时从前往后逐位比较可以发现第一条的 Specificity 值更大,因此上述 html 文档中 Text
的颜色为绿色,与这三条规则所在的位置无关。
下面说明 Specificity 值的计算。
Specificity 计算
Specificity 值由 a
,b
,c
,d
组成,每一个数使用下面规则计算:
- 如果使用 style 属性声明而不是选择器,则
a = 1
否则a = 0
- 计算选择器中 ID 属性的数量 ( 例如
#hello
,不包括[id=hello]
),记为b
- 计算选择其中其他属性 ( 包括
[id=hello]
) 和伪类的数量,记为c
- 计算选择器中元素名称数量和伪元素的数量,记为
d
得到的 Specificity 记为 a-b-c-d
。
下面是一些来自文档的例子:
1 | * {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ |
一些例外
关于 !important
的例外
尽量不要使用 !important
。考虑下面的实践:
- 尽量使用 specificity 而不是
!important
。 - 只在页面使用的 CSS 中用来重写外部的 CSS。
- 在写插件时不要使用。
- 不在全站范围的 CSS 中使用。
相对于使用 !important
,考虑:
- 尽可能利用 CSS 层叠。
- 使用更具体的规则。
- 通过重复选择器来得到更高的 specificity,例如:
#myId span -> #myId#myId span
下面情况可以使用 !important
:
- 重写行内样式。
- 重写高 specificity 的规则。
下面方式可以重写 !important
规则:
- 高 specificity 的
!important
规则。 - 在
!important
后添加的相同选择器的!important
规则。
当然,最好还是重写前面的 !important
规则来避免使用 !important
。
:is()
、:not()
的例外
计算 specificity 时,这两者不计为伪类,但其参数包含的选择器用来计算 specificity。
1 | /* 0-0-1-2 */ |
:where()
的例外
该伪类的 specificity 总是 0。
其他注意事项
- 树层次上的接近不会影响 specificity 的计算。
- 直接目标样式相对于继承样式优先考虑。
参考资料
Specificity - MDN
specifishity
CSS - Specificity
Specificity Calculator