学习前提
能看懂标签、类和 ID 选择器,知道外部 CSS 如何引入。
本课完成后你能做什么
按顺序诊断样式冲突,而不是盲目增加 !important;解释为什么父元素的颜色能影响子元素。
先理解机制
层叠不是单纯比较谁写在后面。浏览器还要考虑规则是否适用、来源、重要性、层以及选择器优先级等;在同一比较层级中才由源码顺序决定平局。初学时可以先控制变量:只比较同一张作者样式表、相同层、普通声明,再观察 ID、类和标签选择器的差异。
继承发生在一个属性没有从元素自身得到相应值的情况下。color 和许多字体属性会继承,而边框、宽度通常不会。父级选择器再具体,也不能靠“继承的高优先级”压过子元素直接指定的普通颜色。理解这个区别能解释为什么修改 body 的颜色不会改变所有链接。
可运行示例
<style>
body { color: #234; }
p { color: #964; }
.note { color: #286c4d; }
p.note { color: #235b80; }
</style>
<p class="note">The paragraph is blue. <span>This span inherits it.</span></p>
推演与验证
预测最终段落颜色,再打开计算样式验证。删掉 p.note,绿色类规则应获胜;把 p 规则挪到最后,它仍不能打败更具体的 .note。再给 span 直接设置 color,观察父级颜色不再控制它。每次只改一个条件,才能知道结果来自哪个规则。
常见错误与边界
!important 改变的是声明的重要性,不能修复错误选择器、错误路径或无效值。不要把优先级当成一个可随意相加的十进制数字。组件样式宜保持较低且稳定的优先级,避免不断升级选择器形成难以覆盖的链条。
动手练习
解释 .panel p 与 p.notice 谁更具体,并写一个不使用 !important 的改法,让 notice 拥有稳定的警示颜色。
参考解法与理由
二者都包含一个类和一个类型选择器,在同源同层等其他条件一致时由顺序决定。可以把基础文字颜色写在 .panel 上让其继承,再对 .notice 直接设色,减少结构耦合,而不是把选择器越来越长。
<style>
.panel { color: #345; }
.notice { color: #963b24; }
</style>
<div class="panel"><p class="notice">Check your input.</p></div>
深入实验:层叠不是只比选择器分数
在同一来源的普通声明中,层的顺序会先于选择器优先级参与比较。把所有冲突都用!important压住,会让后来维护更加困难。保存下面完整页面,观察文字颜色,再在DevTools逐条取消声明。
<!doctype html><html lang="en"><meta charset="utf-8">
<title>Cascade lab</title>
<style>
@layer base, components;
@layer base { #lesson { color: rgb(160, 0, 0); } }
@layer components { .note { color: rgb(0, 90, 0); } }
.note { color: rgb(0, 0, 180); }
</style>
<p id="lesson" class="note">Inspect my computed color.</p>
<script>
console.log(getComputedStyle(document.querySelector('#lesson')).color);
</script></html>预期观察
初始为rgb(0, 0, 180)。禁用未分层的.note规则后变为rgb(0, 90, 0),不是ID规则的红色。
原因、取舍与适用边界
普通的未分层作者样式优先于分层的普通样式;在显式层之间,后声明的components层胜出。因此不能跳过来源、重要性和层直接比较ID数量。继承也不是给父选择器加分:子元素只要有适用的指定值,就不必继承父颜色。重要声明的层顺序会反转,本实验故意不用!important,避免把两个规则体系混在一起。
进阶练习
删除未分层规则,仅调换@layer base, components的顺序。预测颜色并说明这是否适合修复单个按钮。
解法与推理
顺序改为components, base后变红。层顺序是全局架构决定,可能影响许多组件;单个按钮应先检查是否误用了类名、变量或组件状态,而不是为一个例外翻转整站层顺序。