08继承与层叠

本章第 01 课说过,CSS 有两个灵魂概念:继承(Inheritance)和层叠(Cascade)。 继承解释了「为什么给 body 设一次字体,全站文字都跟着变」; 层叠回答了「同一个元素被好几条规则同时点名,到底听谁的」。 这一课把这两个机制讲透——下一课的选择器优先级计算,只是层叠的其中一环。

约 16 分钟 5 个动手实验 灵魂机制

一、什么是继承:孩子自动拿到父级的某些属性

继承(Inheritance):给父元素设了某些属性, 它的子元素、孙元素……整个后代都会自动拿到同样的值, 不用一个个去设。这就是为什么老手只在 body 上写一次 color 和 font-family,全站文字就统一了。

但注意:不是所有属性都继承。 给父元素加边框,孩子们并不会每人都长一个边框——否则页面早乱套了。

只给父级 .parent 设了 color / font-size / line-height,两个孩子全跟着变;而 border / padding 只有父级自己有。把 .parent 的 color 改成 #4E7A52,看两段文字一起变绿
继承是「顺着 DOM 树往下流」的:只向下、不向上、不横向。 孩子的兄弟之间互不影响,父级更不会倒过来学孩子。

二、哪些属性继承、哪些不继承

不用死记硬背整张表,记住一句话就够: 和「文字排版」相关的属性才继承,和「盒子占位」相关的都不继承。 道理很直觉——文字样式当然希望全篇统一;而盒子尺寸边距各有各的算盘,绝不能乱传。

继承速查表:文字类往下传,盒子类不传
分类属性继承吗为什么
字体类font-family / font-size / font-weight / font-style✓ 继承全站字体统一,设一次就够
文本类color / line-height / text-align / text-indent / letter-spacing✓ 继承段落排版跟着整体风格走
其他visibility / cursor / list-style✓ 继承父级隐藏,孩子当然一起藏
盒子类width / height / margin / padding✗ 不继承每个盒子的尺寸边距各管各的
边框背景border / background / border-radius✗ 不继承不然每个孩子都复制一套边框背景,页面没法看
布局类display / position / float / flex✗ 不继承布局方式逐元素单独指定
记忆法:把属性想成「基因」和「衣服」——文字样式是基因,代代相传; 盒子属性是衣服,每人穿自己的,谁也别抢谁的。

三、四个控制词:inherit / initial / unset / revert

CSS 给所有属性预备了四个通用关键字, 用来精确控制「这个值从哪来」:

四个通用关键字:值的来源遥控器
关键字含义典型用途
inherit强制继承:不管这属性天生继不继承,都拿父级的值让链接、按钮继承父级文字颜色
initial回到属性的「规范初始值」(如 color 的初始值是黑色)清掉自己写过的某条声明
unset自动二选一:天生继承的属性 = inherit,其余 = initial「恢复自然状态」的懒人键
revert回滚到浏览器默认样式(用户代理样式表那一层)撤销作者样式,恢复浏览器原样
奇效一:.force 用 border: inherit 强行继承了父级的金框;奇效二:.plain-link 用 color: unset + text-decoration: unset 变回普通文字。把 inherit 改成 initial,看子级边框消失
unset 是最常用的那个:它「懂规矩」—— 该继承的继承、该归零的归零。拿不准用哪个时,先试 unset。

四、all 属性:一键重置的「核弹按钮」

all 是一个简写属性,代表「除了 direction 和 unicode-bidi 之外的所有属性」。给它一个控制词,等于一次性把几百个属性全部设置。 最常见的用法是 all: unset——把元素剥成「裸奔状态」, 做自定义按钮、重置第三方组件时特别好用。

左边是浏览器默认样式的 button(灰底、边框、内边距);右边被 all: unset 剥光,只剩纯文字,再从零定制。把 all: unset 那行删掉,看右边按钮瞬间「穿回衣服」
all: unset 连 cursor、 display 都会一起清掉——剥光之后记得把需要的(比如 cursor: pointer)亲手补回来,否则按钮连「手型」都没了。

五、层叠三要素:听谁的,看这三条

同一个元素的同一个属性,被好几条规则同时点名时, 层叠(Cascade)按下面三条依次裁决—— 前一条分出胜负,后面就不用比了:

层叠裁决三步走:逐级比较,先到先得
顺序比什么规则
①来源与重要性!important 声明 > 作者样式(你写的)> 浏览器默认样式
②优先级(Specificity)行内样式 > id 选择器 > 类选择器 > 元素选择器——详细打分规则见 09 选择器进阶
③书写顺序前两条打平手时,后写的赢(后来者居上)
两条规则优先级完全相同(都是单个类选择器),.btn-b 写在后面所以生效,按钮是砖红色。把 .btn-b 整块剪切到 .btn-a 前面,看按钮变成金色——顺序即胜负
「后写的赢」也是 CSS 里 C(层叠)的本义: 同名规则像瀑布一样往下流,最后的声明盖掉前面的。注意它只在 优先级打平时登场——优先级高的写在前面照样赢。

六、!important:能掀桌子的王牌,别乱打

在声明后面加 !important,这条声明就跳到了层叠第一关的顶端: 压过一切普通声明,包括行内样式。 它合理的使用场景很窄——覆盖第三方组件库的样式、覆盖你改不了的行内样式。 滥用它会引发「军备竞赛」:你加一个 !important, 下次别人只能再加一个更高的来压你,最后满屏感叹号,谁也动不了谁。

两个按钮都写了行内 style(层叠里行内优先级极高),但右边被 !important 强行压成了砖红。把 !important 删掉,右边立刻变回行内的绿色
团队铁律:能不用 !important 就不用。 样式不生效时,先去 DevTools 查优先级(09 课教你算分), 别第一时间掏王牌——掏多了,代码就没人敢维护了。

七、本章小结

  • 继承(Inheritance):后代自动拿到父级的某些属性,只向下传。文字排版类属性继承,盒子布局类不继承。
  • 四个控制词:inherit 强制继承、initial 回初始值、unset 自动二选一、revert 回浏览器默认。
  • all: unset 一键剥光元素所有样式,是定制按钮 / 重置组件的利器,剥完记得补 cursor。
  • 层叠(Cascade)三步裁决:先比来源与重要性,再比优先级,打平才比书写顺序——后写的赢。
  • !important 能压住行内样式,是掀桌王牌;合理场景只有覆盖第三方 / 行内样式,滥用必成「军备竞赛」。
  • 优先级的详细打分(行内 > id > 类 > 元素),下一课 09 选择器进阶 见分晓。
动手练习:随便打开一个你常逛的网站,F12 → Elements 选中一个标题, 在右下角 Styles 面板里找一条被划掉的声明——它就是层叠的「败方」。 鼠标悬停上去看提示,回答三个问题:它输给了谁?输在优先级还是书写顺序? 勾选 / 取消勾选生效的那条声明,页面会发生什么?想通这一次,层叠就真懂了。