返回笔记列表
01 · NOTES / WebGIS 开发

第 29 节 · 层叠、继承与优先级全解

2026 年 9 月 1 日

第 29 节 · 层叠、继承与优先级全解

📌 版本信息:基于 CSS Cascading and Inheritance Level 5(现行规范;2026-08-29 核对) 📚 来源:MDN 层叠CSS Specificity 完整算法

一、这一节的目标

  1. 背下优先级计分的完整算法(三位数)
  2. 理解层叠的完整裁决顺序:来源与重要性 → 层 → 优先级 → 顺序
  3. 掌握继承:哪些属性会传给子孙、怎么控制
  4. !important 为什么是禁手、什么情况是唯一解
  5. 拥有"读到任意一条 CSS 就知道它赢不赢"的判断力

二、优先级计分:三位数算法

每条选择器算一个三位数(A-B-C),高位大者胜:

计什么 每个计 1 分
A(百位) ID 选择器 #app
B(十位) 类选择器、伪类、属性选择器 .card:hover[type="text"]
C(个位) 元素选择器、伪元素 p::before
* {}                 /* 0-0-0 */
p {}                 /* 0-0-1 */
p:hover {}           /* 0-1-1 */
.card p {}           /* 0-1-1(同分,看书写顺序) */
#app .map .btn {}    /* 1-2-0 */
style="…"(行内)      /* 视为 1-0-0-0(更高一位) */
!important           /* 打破一切(最后一节细说) */

三个必懂细节:

  1. 通配符 *、组合符(>、空格)不记分——.card > p 还是 0-1-1
  2. 同级比较看源码顺序:后写的赢
  3. 优先级是"整条选择器"的合计,不是"最狠的那段":#app .card 是 1-1-0

💡 直觉训练:看到 #sidebar ul li a:hover(1-1-3)你能立刻报分——这种判断力在排查"样式不生效"时是超能力。


三、层叠的完整裁决顺序

同一条声明冲突时,浏览器按下面顺序裁决(越往下越强):

1. 来源与重要性:
   浏览器默认样式 < 用户样式 < 开发者样式
   (每层内部又分普通 / !important,!important 反转顺序)
2. @layer 层级(v4 Tailwind 的底层机制之一)
3. 优先级(A-B-C 计分)
4. 源码顺序(后者胜)

实战结论:日常 95% 的冲突在第 3、4 步就分出胜负——你只需要算分 + 知道顺序。剩下 5%(第三方库覆盖)才需要 !important 或更高优先级选择器。


四、继承:哪些属性会"传家"

默认继承的(文字类):colorfont-*(family/size/weight)、line-heighttext-alignletter-spacingvisibility

默认不继承的(盒子类):widthheightmarginpaddingborderbackground

body { color: #333; font: 14px/1.6 sans-serif; }
/* 全页文字自动继承这两条——这就是"在 body 上设全局字体"的原理 */

/* 三个继承控制关键字 */
color: inherit;    /* 强制继承父亲 */
color: initial;    /* 回到规范初始值(黑) */
color: unset;      /* 有继承就继承,没有就初始(聪明但少用) */

💡 为什么按钮里的字不信 body 的字体?——浏览器给 button/input 的默认样式带了自己的 font,覆盖了继承。老项目的"reset 样式"主要就是在修这些浏览器默认值(Tailwind 的 preflight 也干这个)。


五、!important:最后手段

/* 反转层叠:带 important 的普通声明 > 别人的 important > 所有普通声明 */
.card { color: red !important; }

为什么是禁手:它不参与计分、只能靠另一条 important 反制——用三个以后整个项目的优先级体系报废,后来者只能加更多 important("important 军备竞赛")。

合法场景(几乎全部是"覆盖第三方/浏览器固执样式"):

  1. 覆盖第三方库的行内样式(它 style="…" 你没法提高选择器)
  2. 无障碍用户样式表
  3. 全局兜底(如 .hidden { display: none !important }——Tailwind 就是这么定义 hidden 的)

六、实战方法论:样式不生效的排查树

样式没生效?
├─ 1. 选择器选中它了吗?→ DevTools Elements 里看该元素
│     (没有任何命中 → 选择器写错/结构变了)
├─ 2. 命中了但被划线(删除线)?→ 被更高优先级覆盖
│     → 看是哪条赢的,算一算双方分值
├─ 3. 赢的来自哪?→ Sources 面板看文件,第三方库就用更高优先级或 important
└─ 4. 还不对?→ 检查拼写、选择器是否需要 > 加深、是否被层/顺序反转

七、自测题

  1. 报出 #app .nav li a.active 的优先级三数。
  2. 同为 0-1-1 的两条规则,谁赢?
  3. border 会继承吗?font-size 呢?
  4. 为什么 <button> 里的字不受 body 字体影响?
  5. 覆盖第三方库行内样式,除了 !important 还有招吗?

参考答案

  1. 1-2-2(1 个 ID、2 个类、2 个元素——.nav.active 是类,li a 是元素)。
  2. 源码顺序靠后的赢。
  3. border 不继承;font-size 继承。
  4. 浏览器默认样式给表单控件自带 font,声明比继承优先。
  5. 行内样式只能用 !important 对抗(行内 > 一切选择器,important 才能跨过行内);或改库源码/配置项。

八、下一步

规则懂了 → 第 30 节:CSS 单位与变量,尺寸世界全解析 + 自定义属性(Tailwind v4 主题的底层)。

TAGSweb