CSS 优先级与层叠

当多条 CSS 规则指向同一个元素的同一个属性时,浏览器需要决定谁说了算。这个决策过程就叫层叠(cascade),而决定胜负的机制是优先级(specificity)

优先级计算

优先级可以看作一个三元组 (a, b, c)

级别选择器类型权重
aID 选择器(#header1, 0, 0
bclass、属性、伪类(.btn, [type], :hover0, 1, 0
c类型标签、伪元素(div, ::before0, 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

层叠规则

当优先级相同时,按以下顺序决定谁生效:

  1. 来源:用户代理(浏览器默认样式)→ 作者样式 → !important 用户样式 → !important 作者样式
  2. 特指性:优先级高的胜出
  3. 书写顺序:后写的覆盖先写的
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 */

可继承的属性包括:

  • 文字类colorfont-familyfont-sizefont-weightline-heighttext-align
  • 列表类list-style
  • 光标cursor

不可继承的属性:

  • 盒模型类marginpaddingborderwidthheight
  • 布局类positiondisplayfloat
  • 背景类backgroundbackground-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;
}