CSS 层叠、继承与源顺序
把层叠全流程、继承属性与源顺序放在同一模型里,解释“最终样式从哪来”。
#synthesis
#growing
#frontend
#css
[!info] related notes
- 所属:层叠与选择器 MOC
- 路线:CSS 学习路线
- 相关:优先级与特异性 · CSS 变量
CSS 层叠、继承与源顺序
这个概念为什么出现
“我写了 color,为什么是别的颜色?”答案可能是:
- 被更具体规则覆盖
- 被继承自祖先
- 来自用户代理默认
- 来自另一张样式表更靠后的同级规则
- 来自
@layer/ important 层
层叠是 CSS 的操作系统。
[!abstract] 一句话理解 最终值 = 候选声明经层叠排序后的胜者;部分属性可继承,源顺序只在同级平局时决胜。
最小可运行示例
场景:表格单元格文字颜色“来路不明”
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<style>
body { color: #0f172a; } /* 继承起点 */
.table { color: #334155; }
.table td { /* 未设 color,继承 .table */ }
.table td.em { color: #b91c1c; } /* 直接命中 */
</style>
</head>
<body>
<table class="table">
<tr>
<td>普通单元格</td>
<td class="em">低库存</td>
</tr>
</table>
</body>
</html>
期望:普通单元格继承 .table 的灰蓝;.em 直接声明胜出为红。
结合场景关注点
- 继承 ≠ 选择器命中。
- 直接声明再弱,也通常压过继承来的值。
- 调试先问:有没有直接命中的 color?
核心模型
层叠主线(教学)
- 收集所有命中该元素+该属性的声明
- 按来源与层(user agent / user / author,以及 cascade layers、important)排序
- 同一层叠优先档位内比较特异性
- 特异性相同时,若涉及
@scope,先比较作用域接近程度,再比较源顺序 - 层叠选出声明;没有声明或遇到相应关键词时,通过继承、初始值等默认规则得到指定值,随后求计算值与使用值
继承
- 典型继承:
colorfont-*line-height等 - 典型不继承:
marginpaddingborderbackground等 inherit/initial/unset/revert是显式控制关键词
源顺序
只在其它条件相同时成为决胜局。把“把文件放后面”当唯一策略会与特异性打架。
@layer(现代工程)
层叠层允许框架、重置、组件与工具类在特异性之前约定优先级。同一来源下,普通声明中后声明的层胜过前面的层,未分层的普通声明高于分层声明;!important 的层顺序反转,分层 important 声明高于未分层 important 声明。动画、过渡与内联声明也有专门顺序,完整算法以规范为准。
设计动机
CSS 必须合并多来源样式且保持可覆盖性。继承减少重复文本样式;层叠提供冲突解决;源顺序提供同级确定性。
常见误区
[!warning] 常见误区:继承来的样式有特异性 继承值不参与选择器特异性比赛;被直接声明覆盖是常态。
工程实践
- 重置样式保持低特异性
- 设计 token 放在
:root变量,组件消费变量 - 工具类与组件 CSS 冲突时优先看 layer/顺序配置
- DevTools Computed 是真相来源
本节总结
层叠回答“谁赢”,继承回答“没写时从哪来”,源顺序回答“平局怎么办”。
自测题
- 在来源、层、important 等前置条件相同时,为什么后写的元素选择器盖不过先写的类选择器?
color: inherit解决什么?
参考答案
- 类特异性更高,源顺序轮不到决胜。
- 强制使用父元素的计算 color,而不是初始值或其它来源。
延伸阅读
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| css-cascade-5 | 规范 | 层叠 |
| MDN Inheritance | 文档 | 继承 |