Skip to content

层叠与继承

基于 CSS 现代标准 · 核于 2026-06

速查

  • 层叠裁决四步,逐步定不了才看下一步:① 来源与重要性 → ②(层叠层)→ ③ 特异性 → ④ 书写顺序
  • 普通声明来源由弱到强:浏览器(UA)< 用户 < 作者(你写的)
  • !important 反转来源顺序:作者 !important < 用户 !important < 浏览器 !important
  • 完整优先级(低→高):UA 普通 → 用户普通 → 作者普通 → 行内普通 → 动画 → 作者 !important → 用户 !important → UA !important过渡
  • 动画(@keyframes)压过一切普通声明;过渡(transition)优先级最高,连 !important 都压
  • !important 是「逃生舱」不是常规手段——优先用 @layer:where() 管理优先级
  • 没有任何规则命中某属性时:可继承属性(color/font 等)取父级计算值,否则用属性初始值
  • 五个全局关键字:inherit(强制继承父值)、initial(属性初始值)、unset(继承属性当 inherit、否则当 initial)、revert(回退到低来源的值)、revert-layer(回退到上一层叠层的值)

层叠:冲突裁决的四个阶段

「层叠」(cascade)是 CSS 名字里那个 C,指多条规则命中同一元素同一属性时决出唯一胜者的算法。它分四个阶段,像漏斗一样逐级筛选——上一阶段能分出胜负就停,分不出才进入下一阶段:

  1. 来源与重要性(origin & importance)——样式从哪来、带不带 !important
  2. 层叠层(cascade layers)——作者样式内部按 @layer 排序(下一页专讲,这里先略);
  3. 特异性(specificity)——选择器谁更具体(见 上一页);
  4. 书写顺序(order of appearance)——以上全平时,后写的赢。

注意顺序:来源与重要性在最前,比特异性更先决出。所以一条来自浏览器默认样式表、特异性再高的规则,也压不过你写的任意一条普通作者规则——因为「作者来源」整体就比「UA 来源」高一档。

第一阶段:来源与重要性

CSS 声明按「从哪来」分三种来源,普通声明(不带 !important)的优先级由低到高

来源是什么普通声明优先级
浏览器(user-agent)浏览器内置默认样式(<h1> 默认大字号等)最低
用户(user)用户在浏览器里设的偏好、用户样式表、扩展注入
作者(author)你写的 CSS(外链 / <style> / 行内)最高

这解释了日常现象:你写的 h1 { font-size: 2rem } 总能盖过浏览器默认的 <h1> 字号——作者来源天然高于 UA 来源。

!important 把来源顺序倒过来

当声明带 !important,它进入一个独立的、更高的重要性档,而且这一档里来源顺序整个反转

普通声明:   UA  <  用户  <  作者         (作者最强)
!important: 作者 <  用户  <  UA          (UA 最强,完全反转)

为什么反转?这是为用户兜底无障碍:如果某个用户因视力问题,用浏览器设置强制放大字体(用户 !important),网站作者就不该能用自己的 !important 把它再压回去——所以用户 !important 必须高于作者 !important

把动画与过渡塞进来:完整优先级阶梯

除了来源,激活中的动画与过渡也有特殊档位。把所有情况拼起来,从低到高的完整优先级是:

档位(低 → 高)说明
1. UA 普通声明浏览器默认
2. 用户普通声明用户偏好
3. 作者普通声明你写的普通样式(含分层 / 未分层,见下页)
4. 行内 style(普通)元素 style=""
5. 动画 @keyframes激活的关键帧动画,压过以上所有普通声明
6. 作者 !important你写的 !important
7. 用户 !important用户的 !important
8. UA !important浏览器的 !important
9. 过渡 transition最高,连 !important 都能压

为什么动画 / 过渡能压 !important

动画和过渡正在「进行时」,它们的本职就是逐帧改变视觉状态。如果一条 !important 能在动画中途把属性钉死,动画就会卡住、抖动。所以规范让激活中的过渡优先级排在最顶(动画稍低,但仍高于所有普通声明)——保证视觉过渡顺滑。这也意味着:用 !important 去「锁」一个正在过渡的属性,是锁不住的。

第四阶段:书写顺序

当来源、层、特异性全部打平,最后写的声明获胜。无论是同一文件里靠后的规则、靠后加载的 <link>,还是同一声明块里重复的属性,都遵循「后来居上」:

css
.alert {
  color: orange;
}
.alert {
  color: crimson; /* 同特异性,后写 → 最终 crimson */
}

!important:逃生舱,不是常规工具

!important 能赢,但它破坏了层叠的可预测性:一旦用了,下次想覆盖就只能再来一个 !important,迅速演变成「!important 军备竞赛」,整套样式失控。

什么时候可以用:

  • 覆盖无法修改的第三方内联样式(如某些 widget 用 JS 写死了 style);
  • 工具类 / 原子化 CSS 框架里,明确希望「这个类一锤定音」的场景(且框架已统一管理)。

什么时候别用:日常组件样式覆盖。现代 CSS 给了两个更优雅的替代:

  • @layer:把第三方 / 基础样式放进较低的层,你的普通样式天然胜出,不必 !important(见 级联层实战);
  • :where():给基础样式归零特异性,让业务样式轻松覆盖(见 特异性计算)。

MDN 的官方建议

MDN 明确建议:与其用 !important 覆盖外部样式,不如用 @import ... layer(name) 把外部样式表导入低优先级的层。这是 2026 年管理样式优先级的首选范式。

继承:层叠之外的「兜底」

层叠负责「多条规则冲突时选谁」。但如果没有任何规则命中某元素的某属性呢?这时轮到继承初始值兜底。

CSS 属性分两类:

  • 可继承属性:未显式赋值时,自动取父元素的计算值。多为文字排版相关:colorfont-familyfont-sizeline-heightletter-spacingvisibilitylist-style 等。
  • 非继承属性:未赋值时,取该属性在规范里定义的初始值(而非「父级的值」)。多为盒模型 / 布局相关:marginpaddingborderwidthheightbackground 等。
css
body {
  color: #333;
  border: 1px solid red;
}
/* <body> 里的 <p> 没写任何样式时: */
/* color → 继承得到 #333(可继承)           */
/* border → 用初始值 none(非继承,不会继承红框)*/

「直接命中」永远压过「继承而来」

继承值是最弱的值。只要有任何一条规则直接命中该元素的该属性(哪怕特异性极低、哪怕来自 UA 默认样式表),它就会盖过从父级继承来的值。所以「父级设了 color 但子元素颜色不对」时,先查是不是有别的规则直接命中了子元素。

五个全局关键字:手动控制继承与回退

任何 CSS 属性都能接收这五个「CSS 通用关键字」,用来精确控制取值来源:

css
.demo {
  color: inherit; /* 强制取父元素的计算值——让非继承属性也继承 */
  margin: initial; /* 重置为该属性的规范初始值(margin 的初始值是 0) */
  padding: unset; /* 可继承属性→当 inherit;非继承属性→当 initial */
  border: revert; /* 撤销作者样式,回退到更低来源(用户/UA)的值 */
  display: revert-layer; /* 回退到「上一个层叠层」里该属性的值 */
}

逐个说清,它们的差别全在「回退到哪里」:

关键字取什么值典型用途
inherit父元素该属性的计算值borderbackground 等非继承属性显式继承父级
initial该属性在 CSS 规范里定义的初始值(不是浏览器默认!)把属性「清零」到规范基线
unset可继承属性 → 同 inherit;非继承 → 同 initial一键「擦掉作者设定、回到自然状态」
revert回退到更低来源(用户 / 浏览器)会产生的值撤销作者样式、保留浏览器默认外观
revert-layer回退到前一个层叠层里该属性的值@layer 中「撤销本层、露出下层」(见下页)

initial ≠ 浏览器默认外观

最常见的误解:以为 display: initial 会让 <div> 回到 block。其实 display规范初始值是 inline,所以 div { display: initial } 会把 div 变成 inline!想「恢复浏览器默认外观」应该用 revert(回退到 UA 样式表的 display: block),而不是 initialinitial 给的是规范定义的初始值,常与直觉里的「默认」不同。

unsetrevert 也别混:

css
/* 假设 UA 给 <a> 设了 color: blue(蓝色链接) */
a {
  color: red;
} /* 作者样式 */
.reset-unset {
  color: unset; /* color 可继承 → 取父级 color,可能是黑色正文色 */
}
.reset-revert {
  color: revert; /* 撤销作者样式 → 回到 UA 的蓝色 */
}

unset 走「继承/初始值」逻辑,revert 走「回退低来源」逻辑——前者可能露出父级文字色,后者会露出浏览器的蓝色链接。

小结

层叠是「来源与重要性 → 层 → 特异性 → 书写顺序」的四级漏斗,!important 把来源反转、动画与过渡享有最高档;没规则命中时由继承(可继承属性)或初始值兜底,五个全局关键字让你手动选择回退方向。其中第二阶段「层叠层」的威力——能让低特异性样式稳赢高特异性样式——值得单独一页:@layer 级联层实战