CSS Handbook · 基础与层叠

第一章 / 1.2 层叠与继承

第一章 · 1.2 节

层叠与继承


CSS 的全称"层叠样式表"里,"层叠"(Cascade)二字点明了它的核心运作机制:当多条规则同时作用于同一个元素时,浏览器需要一套算法来决定最终生效的是哪一条。理解层叠与继承,是排查"样式怎么不生效"的根本功夫。

层叠的三个维度

当同一元素的同一属性被多条规则命中时,浏览器依次按以下维度决出胜负:

  1. 来源与重要性——用户代理默认样式 < 用户样式 < 作者样式 < 作者 !important < 用户 !important,作者样式的优先级通常最需要关注。
  2. 选择器优先级(specificity)——来源相同时,比较选择器的"精确程度",详见下一节的选择器优先级规则。
  3. 源码顺序——来源与优先级都相同时,后声明的规则覆盖先声明的规则。
提示这也是为什么把「重置样式」放在最前面、把「覆盖样式」放在最后面是常见约定——源码顺序是层叠算法里最后、也最容易被忽视的一环。

优先级速览

选择器优先级可以粗略拆成四级,通常记作 (a, b, c, d):

级别包含示例
a行内样式style="..."
bID 选择器#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,形成优先级军备竞赛。

Chapter 1 · Section 1.2

The Cascade and Inheritance


In the full name "Cascading Style Sheets", the word "Cascade" points straight at its core mechanism: when multiple rules apply to the same element at once, the browser needs an algorithm to decide which one wins. Understanding the cascade and inheritance is the fundamental skill for debugging "why is this style not taking effect".

The Three Dimensions of the Cascade

When the same property of the same element is hit by several rules, the browser settles the contest by the following dimensions in order:

  1. Origin and importance — user-agent default styles < user styles < author styles < author !important < user !important; author styles are usually the ones you need to worry about most.
  2. Selector specificity — when the origins match, the "precision" of the selectors is compared; see the specificity rules in the next section.
  3. Source order — when both origin and specificity match, the rule declared later overrides the one declared earlier.
TipThis is why putting "reset styles" first and "override styles" last is a common convention — source order is the last, and most easily overlooked, link in the cascade algorithm.

Specificity at a Glance

Selector specificity can be roughly split into four tiers, commonly written as (a, b, c, d):

TierIncludesExample
aInline stylesstyle="..."
bID selectors#header
cClass / attribute / pseudo-class selectors.btn、[type], :hover
dType / pseudo-element selectorsdiv、::before

Compare tier by tier, and only move to a lower tier when the higher ones tie; !important and inheritance take no part in this count, and the universal selector * has a specificity of 0. For more complete examples of compound selector specificity, see 2.2 Combinators and Specificity.

!important

.btn {
  color: red !important;
}
Caution!important skips the normal specificity comparison and lifts the declaration straight to an "almost highest" position. Overusing it makes styles hard to override and maintain; in team work it is usually only permitted in rare cases, such as overriding third-party library styles.

Inheritance

Some CSS properties automatically "inherit" from parent elements to their children without being redeclared — these are usually properties related to text and typography, because it matches intuition: set a font on <body> and all the text on the page naturally uses it.

TypeExample properties
Inherited by defaultcolor、font-family、font-size、line-height、letter-spacing、text-align、visibility
Not inherited by defaultmargin、padding、border、width、height、background、display、position

The non-inherited ones are mostly box model and layout properties — if margin could inherit, almost every layout would fall apart.

inherit / initial / unset / revert

Four generic keywords let you explicitly control where any property gets its value from:

KeywordEffect
inheritForces inheritance from the parent element, even if the property does not inherit by default
initialResets to the initial value defined by the CSS specification (independent of inheritance)
unsetActs like inherit if the property inherits by default, otherwise like initial
revertFalls back to the value from the browser's default style sheet (or the user style sheet), ignoring author styles
.reset-all {
  all: unset; /* all can apply to almost every property at once */
}

Common Pitfalls

  • Treating "rules written later always win" as the only rule — source order only decides when specificity ties; a more specific selector wins even if it is written first.
  • Assuming border and background inherit — they do not by default; children need their own declarations or an explicit inherit.
  • Using !important as a "quick fix" for cascade problems — this only postpones the problem, and every later style that wants to override it must add !important too, starting a specificity arms race.