第一章 · 1.2 节
层叠与继承
CSS 的全称"层叠样式表"里,"层叠"(Cascade)二字点明了它的核心运作机制:当多条规则同时作用于同一个元素时,浏览器需要一套算法来决定最终生效的是哪一条。理解层叠与继承,是排查"样式怎么不生效"的根本功夫。
层叠的三个维度
当同一元素的同一属性被多条规则命中时,浏览器依次按以下维度决出胜负:
- 来源与重要性——用户代理默认样式 < 用户样式 < 作者样式 < 作者
!important< 用户!important,作者样式的优先级通常最需要关注。 - 选择器优先级(specificity)——来源相同时,比较选择器的"精确程度",详见下一节的选择器优先级规则。
- 源码顺序——来源与优先级都相同时,后声明的规则覆盖先声明的规则。
提示这也是为什么把「重置样式」放在最前面、把「覆盖样式」放在最后面是常见约定——源码顺序是层叠算法里最后、也最容易被忽视的一环。
优先级速览
选择器优先级可以粗略拆成四级,通常记作 (a, b, c, d):
| 级别 | 包含 | 示例 |
|---|---|---|
| a | 行内样式 | style="..." |
| b | ID 选择器 | #header |
| c | 类 / 属性 / 伪类选择器 | .btn、[type], :hover |
| d | 标签 / 伪元素选择器 | div、::before |
逐级比较,高位相同才比较低位;!important 和继承不参与这套计数,通配符选择器 * 的优先级为 0。更完整的组合选择器优先级示例见 2.2 组合选择器与优先级。
!important
.btn { color: red !important; }
警惕
!important 会跳过正常的优先级比较,直接把该声明提到"几乎最高"的位置。滥用它会让样式变得难以覆盖、难以维护,团队协作中通常仅允许在极少数场景(如覆盖第三方库样式)使用。继承
部分 CSS 属性会自动从父元素"继承"到子元素,无需重复声明——这通常是与文字排印相关的属性,因为它们符合直觉:给 <body> 设置字体,页面里所有文字自然都用这个字体。
| 类型 | 示例属性 |
|---|---|
| 默认继承 | color、font-family、font-size、line-height、letter-spacing、text-align、visibility |
| 默认不继承 | margin、padding、border、width、height、background、display、position |
不继承的多为盒模型与布局相关属性——如果 margin 也能继承,几乎所有布局都会失控。
inherit / initial / unset / revert
四个通用关键字可以显式控制任意属性的取值来源:
| 关键字 | 作用 |
|---|---|
| inherit | 强制从父元素继承,即使该属性默认不继承 |
| initial | 重置为 CSS 规范定义的初始值(与继承无关) |
| unset | 该属性默认可继承则等同 inherit,否则等同 initial |
| revert | 回退到浏览器默认样式表(或用户样式表)中的值,忽略作者样式 |
.reset-all { all: unset; /* all 可以一次性应用到几乎所有属性 */ }
常见误区
- 把"后写的规则一定生效"当作唯一规则——源码顺序只在优先级相同时才起决定作用,一个更精确的选择器即使写在前面也会赢。
- 误以为
border、background会继承——它们默认不继承,子元素需要单独设置或用inherit。 - 用
!important"快速修复"层叠问题——这只是把问题往后拖,后续任何想覆盖它的样式都得跟着加!important,形成优先级军备竞赛。