CSS选择器优先级(Specificity)是CSS中一个核心概念,它决定了当多个选择器同时匹配同一个元素时,哪个样式规则会被应用。理解优先级规则对于编写可预测和可维护的CSS代码至关重要。
什么是选择器优先级
选择器优先级是浏览器用来确定CSS规则重要性的机制。当多个规则同时应用于同一个元素时,浏览器会根据优先级规则选择最具体的规则。
优先级计算规则
根据W3C Selectors Level 4规范,CSS优先级使用四位数值系统 (a,b,c,d) 来表示:
- a: 内联样式数量
- b: ID选择器数量
- c: 类选择器、属性选择器、伪类数量
- d: 元素选择器、伪元素数量
基本计算
css
/* 优先级:0,0,0,1 (1个元素选择器) */
p { color: black; }
/* 优先级:0,0,0,2 (2个元素选择器) */
div p { color: blue; }
/* 优先级:0,0,1,1 (1个类选择器 + 1个元素选择器) */
p.highlight { color: red; }
/* 优先级:0,1,0,1 (1个ID选择器 + 1个元素选择器) */
#header p { color: green; }
/* 优先级:0,1,1,1 (1个ID选择器 + 1个类选择器 + 1个元素选择器) */
#header p.highlight { color: yellow; }
复杂选择器计算
css
/* 优先级:0,0,3,1 (3个类选择器 + 1个元素选择器) */
p.highlight.warning.error { color: red; }
/* 优先级:0,1,2,1 (1个ID选择器 + 2个类选择器 + 1个元素选择器) */
#main .content p.highlight { color: blue; }
/* 优先级:0,2,1,2 (2个ID选择器 + 1个类选择器 + 2个元素选择器) */
#header #nav .item a { color: green; }
特殊选择器的优先级
通用选择器 (*)
优先级:0,0,0,0,不增加任何优先级
css
* {
margin: 0; /* 优先级:0,0,0,0 */
}
组合选择器
组合选择器的优先级是各部分的总和
css
/* 优先级:0,0,0,2 (2个元素选择器) */
div + p { color: red; }
/* 优先级:0,0,1,1 (1个类选择器 + 1个元素选择器) */
.class + p { color: blue; }
伪类选择器
结构伪类(如:nth-child
、:first-child
)按类选择器计算,功能伪类(如:not()
、:is()
、:where()
)有特殊规则
css
/* 优先级:0,0,1,1 (1个伪类 + 1个元素选择器) */
p:nth-child(2) { color: red; }
/* 优先级:0,0,1,1 (1个伪类 + 1个元素选择器) */
p:not(.hidden) { color: blue; }
/* 优先级:0,0,2,1 (1个伪类 + 1个类选择器 + 1个元素选择器) */
p:nth-child(2n of .highlight) { color: green; }
现代选择器的优先级
:is() 伪类
优先级等于括号内最高优先级的选择器
css
/* 优先级:0,0,1,0 (等于 .highlight 的优先级) */
:is(.highlight, .warning) { color: red; }
/* 优先级:0,1,0,0 (等于 #header 的优先级) */
:is(#header, .main) { background: blue; }
:where() 伪类
优先级始终为0,0,0,0,用于重置样式的理想选择
css
/* 优先级:0,0,0,0 */
:where(h1, h2, h3) {
margin: 0; /* 总是可以被覆盖 */
}
:has() 伪类
优先级等于其参数中最具体的复杂选择器的优先级
css
/* 优先级:0,0,0,1 (等于 p 的优先级) */
div:has(p) { border: 1px solid black; }
/* 优先级:0,1,0,0 (等于 #header 的优先级) */
div:has(#header) { border: 1px solid black; }
/* 优先级:0,0,1,0 (等于 .highlight 的优先级) */
div:has(.highlight) { border: 1px solid black; }
:nth-child() 和 :nth-last-child() 伪类
优先级 = 伪类本身的优先级 + 参数中最具体的复杂选择器的优先级
css
/* 优先级:0,0,1,1 (1个伪类 + 1个元素选择器) */
p:nth-child(2) { color: red; }
/* 优先级:0,0,2,1 (1个伪类 + 1个类选择器 + 1个元素选择器) */
p:nth-child(2n of .highlight) { color: green; }
/* 优先级:0,1,1,1 (1个伪类 + 1个ID选择器 + 1个元素选择器) */
p:nth-child(2n of #special) { color: blue; }
优先级比较规则
数值比较
优先级按从左到右的顺序比较四位数值:
css
/* 优先级:0,1,0,1 > 0,0,2,0 */
#header p { color: red; } /* 胜出,因为第一位 1 > 0 */
.class1.class2 { color: blue; }
相同优先级
当优先级相同时,后声明的规则覆盖先声明的规则:
css
p { color: red; }
p { color: blue; } /* 这个会生效 */
!important 声明
!important
声明的优先级最高,但应该谨慎使用:
css
p { color: red !important; } /* 最高优先级 */
#header p { color: blue; } /* 被覆盖 */
实际应用示例
1. 组件样式覆盖
css
/* 基础样式 */
.button {
padding: 10px 20px;
background: #ccc;
}
/* 主题样式 */
.button.primary {
background: #007bff; /* 优先级:0,0,2,0 */
}
/* 状态样式 */
.button.primary:hover {
background: #0056b3; /* 优先级:0,0,3,0 */
}
/* 特殊情况覆盖 */
#special .button.primary {
background: #ff0000; /* 优先级:0,1,2,0 - 最高 */
}
2. 响应式设计
css
/* 移动端 */
.card {
padding: 1rem;
}
/* 平板端 */
@media (min-width: 768px) {
.card {
padding: 1.5rem; /* 相同优先级,后声明生效 */
}
}
/* 桌面端 */
@media (min-width: 1024px) {
.card {
padding: 2rem;
}
}
总结
CSS选择器优先级是CSS层叠机制的核心,理解其计算规则对于编写可维护的样式代码至关重要。记住以下要点:
- 优先级计算:内联样式 > ID选择器 > 类/属性/伪类 > 元素/伪元素
- 数值比较:从左到右比较四个数值
- 相同优先级:后声明的规则覆盖先声明的规则
- !important:最高优先级,但应谨慎使用
- 现代选择器 :
:is()
、:where()
、:has()
有特殊的优先级规则
通过合理使用优先级规则,我们可以创建更加可预测和可维护的CSS代码,避免样式冲突和覆盖问题。