在编写 CSS 时,经常遇到多个规则作用于同一个元素的情况,最终哪个规则生效由选择器的优先级决定。
什么是选择器优先级?
当多个 CSS 规则同时匹配一个元素时,浏览器需要根据一定的规则来决定哪个样式生效。这个规则就是优先级(Specificity)。优先级是一个由四部分组成的权重体系,权重高的规则胜出。如果权重相同,则后定义的规则覆盖先定义的规则(层叠顺序)。
优先级权重计算规则
CSS 选择器的优先级可以表示为四部分:(内联样式,ID 选择器,类/伪类/属性选择器,元素/伪元素选择器)。通常用 (a, b, c, d) 来表示:
- a:内联样式(inline style),即在 HTML 元素的 style 属性中定义的样式。它的优先级最高,记作 1,0,0,0。
- b:ID 选择器的数量,例如 #header,记作 0,1,0,0。
- c:类选择器(如 .box)、伪类选择器(如 :hover)、属性选择器(如 [type=“text”])的数量,记作 0,0,1,0。
- d:元素选择器(如 div)、伪元素选择器(如 ::before)的数量,记作 0,0,0,1。
此外: - 通配符选择器 *、组合器(+、>、~、空格)和否定伪类 :not() 本身对优先级没有贡献,但 :not() 内部的选择器会正常计算权重。
- !important 规则会覆盖任何普通优先级声明,但同属 !important 时仍按优先级比较。
计算示例
示例 1:简单选择器
1 | /* 权重 (0,0,0,1) */ |
对于 <div id="my-id" class="my-class"> 元素,三个规则都匹配,优先级最高的 #my-id 生效,文字为绿色。
示例 2:组合选择器
1 | /* 权重 (0,0,1,1) */ |
对于 <div id="my-id" class="my-class">,第三个规则权重最高(一个 ID + 一个类),生效为绿色。
示例 3:复杂选择器
1 | /* 权重 (0,1,2,1) */ |
计算过程:
- ID 选择器:#nav → 1 个 → b=1
- 类/伪类/属性:.list 和 :hover → 2 个 → c=2
- 元素/伪元素:li、a、::before → 3 个 → d=3
- 内联样式:0 → a=0
最终权重 (0,1,2,3)。
示例 4:内联样式
1 | <div id="box" class="box" style="color: black;">文本</div> |
内联样式权重为 (1,0,0,0),最高,最终文字为黑色。
!important 规则
- !important 写在属性值后面,表示该声明具有最高优先级。
- 它会覆盖任何普通声明(包括内联样式),但如果有多个 !important 规则,则仍然按常规优先级比较。
1 | p { color: red !important; } /* 权重极高 */ |
对于 <p id="text">,虽然 ID 选择器权重更高,但 !important 使红色生效。
1 | p#text { color: red !important; } /* (0,1,0,1) + !important */ |
两者都是 !important,比较权重:第一个有一个 ID,第二个没有,所以第一个生效。
特殊情况的处理
通配符和组合器
通配符 * 以及组合器(+、>、~、空格)本身不计入权重,但组合器连接的选择器分别计算。
1 | * { color: black; } /* (0,0,0,0) */ |
:not() 伪类
:not() 本身不计入权重,但其内部的选择器正常计算。
1 | div:not(.hidden) { color: red; } /* (0,0,1,1)(一个元素 + 一个类) */ |
继承的样式
继承的样式没有优先级,任何直接作用于元素的规则都会覆盖继承的值。
优先级比较的常见误区
- 误区一:认为类选择器比元素选择器权重高,这是正确的,但需要精确计算数量。
- 误区二:认为 !important 可以无视任何规则,但实际上多个 !important 仍要比较权重。
- 误区三:认为行内样式权重无限大,但实际上它只是 (1,0,0,0),可以被 !important 覆盖。
- 误区四:认为权重可以进位,比如 10 个类选择器可以超过 1 个 ID 选择器。权重不进位,无论多少个类选择器,都无法超过一个 ID 选择器。例如 (0,0,11,0) 仍然小于 (0,1,0,0)。
总结
CSS 优先级规则可以概括为以下层级(从高到低):
1 | ┌───────────────────────────┐ |
权重计算口诀:内联最高,ID 次之,类第三,元素最后。!important 权倾天下,但内斗仍按上述规则。