CSS 优先级与层叠
当多条 CSS 规则指向同一个元素的同一个属性时,浏览器需要决定谁说了算。这个决策过程就叫层叠(cascade),而决定胜负的机制是优先级(specificity)。
优先级计算
优先级可以看作一个三元组 (a, b, c):
| 级别 | 选择器类型 | 权重 |
|---|---|---|
| a | ID 选择器(#header) | 1, 0, 0 |
| b | class、属性、伪类(.btn, [type], :hover) | 0, 1, 0 |
| c | 类型标签、伪元素(div, ::before) | 0, 0, 1 |
比较时从左到右:先比 a,相同再比 b,再比 c。
css
/* 优先级: (0, 0, 1) */
p { color: black; }
/* 优先级: (0, 1, 0) */
.article { color: blue; }
/* 优先级: (1, 0, 0) */
#main-content { color: red; }
/* 优先级: (0, 1, 1) */
p.article { color: green; }
/* 优先级: (0, 0, 2) */
article p { color: gray; } html
<!-- 最终颜色:red(#main-content 优先级最高) -->
<h1 id="main-content" class="article">标题文字</h1> 通配选择器 *、组合器(>、+、~)、:where() 不贡献优先级。:is() 和 :not() 取参数中最高优先级。
优先级比较示例
css
/* A: (0, 0, 2) — 两个类型选择器 */
nav a { color: blue; }
/* B: (0, 1, 0) — 一个 class */
.nav-link { color: green; }
/* C: (0, 1, 1) — class + 类型 */
a.nav-link { color: red; } html
<nav>
<a class="nav-link" href="/">首页</a>
<!-- 颜色:red,C 优先级最高 -->
</nav> !important
在声明末尾加 !important 会将该声明提升为最高优先级,覆盖所有普通声明:
css
p {
color: red !important;
}
.article p {
color: blue; /* 被 !important 覆盖,无效 */
} !important 是核武器——一旦使用,后面的常规覆盖全部失效。它打破了 CSS 的层叠本质,让调试变得极度困难。仅在以下场景考虑使用:
- 覆盖你无法修改的第三方库样式
- 工具类(如
.hidden { display: none !important; }) 在常规开发中,应通过提升选择器优先级来覆盖样式,而不是依赖!important。
层叠规则
当优先级相同时,按以下顺序决定谁生效:
- 来源:用户代理(浏览器默认样式)→ 作者样式 →
!important用户样式 →!important作者样式 - 特指性:优先级高的胜出
- 书写顺序:后写的覆盖先写的
css
/* 两条规则优先级相同,都是 (0, 0, 1) */
p { color: black; }
p { color: blue; } /* 这条生效,因为写在后面 */ 继承
有些 CSS 属性会从父元素继承到子元素。例如,在 <body> 上设置 color,所有子元素都会继承这个颜色(除非子元素显式指定了自己的 color):
css
body {
color: #1e293b;
font-family: system-ui, sans-serif;
}
/* body 内所有文字都是 #1e293b,字体为 system-ui */ 可继承的属性包括:
- 文字类:
color、font-family、font-size、font-weight、line-height、text-align - 列表类:
list-style - 光标:
cursor
不可继承的属性:
- 盒模型类:
margin、padding、border、width、height - 布局类:
position、display、float - 背景类:
background、background-color
强制继承
使用 inherit 关键字可以强制子元素继承某个不可继承的属性:
css
.parent {
border: 2px solid #2563eb;
}
.child {
border: inherit; /* 强制从父元素继承边框 */
} html
<div class="parent">
<div class="child">子元素 — border 从父元素继承</div>
</div> 其他特殊值关键字
| 关键字 | 作用 |
|---|---|
initial | 重置为 CSS 规范定义的初始值 |
inherit | 强制继承父元素的值 |
unset | 可继承属性等同于 inherit,不可继承属性等同于 initial |
revert | 回退到浏览器默认样式 |
css
/* 去掉一个链接的默认外观,变回普通文字 */
a.reset {
color: unset;
text-decoration: unset;
}