别被继承坑了:CSS属性继承性分类与实战避坑指南
写 CSS 时,我经常被问到"为什么这个 button 里的 font-size 没有继承父级的?""为什么我给 div 设置了 color,里面的 p 标签就自动变色了?"——这些问题背后,全都是属性继承在搞鬼。搞清楚哪些 CSS 属性能继承、哪些不能,你写样式的速度至少快一倍,排查样式问题的效率更是质的提升。
这篇文章会把 CSS 里的继承机制彻底讲透。我会按类别把所有常见属性的继承性梳理清楚,配上速查表、实战案例和踩坑记录,无论你是刚接触 CSS 的新手,还是写过几年样式但总被继承搞晕的老开发,都可以直接把里面的结论拿来用。
1. 继承到底是怎么回事:先建立正确的直觉
1.1 一个最简单的现象:color 为什么会"传下去"
试想下面这段代码:你在 body 上设置了color: #333,结果里面所有的文本、所有的标题、所有的段落,全部变成了深灰色。你没在这些元素上写任何 color 规则,但它们都"自动"拿到了这个颜色。
这就是继承最直接的体现:当一个父元素的属性值没有被子元素的规则覆盖时,子元素可以直接借用父元素的最终值。浏览器在计算每个元素的实际样式时,会先查这条属性有没有在自身声明过,没有的话就往父元素看,父元素也没有就继续往上,直到找到祖先里的声明,或者退回浏览器默认样式表。
这套机制的底层逻辑其实很朴素:设计浏览器的人把"用于决定视觉外观"的属性(比如字体、颜色)设计为可继承,因为这类属性和文字内容强相关,通常希望整块文本区域保持一致的外观。而像 width、margin 这类"决定布局结构"的属性,每个元素都有各自的盒子,强行继承反而会导致毫无意义的连锁反应,所以默认就不继承。
1.2 用生活类比理解继承规则
你可以把 CSS 的继承想象成学校里的"校服规定"。学校(html 元素)规定学生要穿校服(比如color: blue),那么各班(body)、各小组(div)、每个学生(p、span)默认都会穿校服。但有个"刺头"学生(某个内联样式或者更具体的类选择器)非要穿自己的卫衣(color: red),那么他单独写的那条规则就会覆盖校服规定。
关键在于:哪些"规定"具有全校强制性,哪些只作用于特定元素?比如"每个学生都有独立的课桌、独立的教室"这种规定,就不可能全校传下去——每个教室有每个教室的布局。对应到 CSS 里,width、height、margin、padding 这类"布局参数"就跟教室一样,每个标签的盒子互不相同,不能继承,如果继承了,一个 div 里套一个 div,整个网页布局直接乱套。
有了这个直觉之后,我们再往下看具体分类,你会发现记起来特别快:凡是直接控制某个标签自身盒子尺寸和内边距的属性基本不继承;凡是描述文本外观、排版、列表样式的属性,绝大多数都会继承。
1.3 两个容易混淆的概念:继承和层叠
讨论继承之前,必须先讲清楚一个前提,不然你后面看 Computed 样式时会怀疑人生。很多人把"层叠(cascade)"和"继承(inheritance)"当作一回事,其实它们是完全不同的两个维度。
层叠解决的是"多个规则同时命中时,谁说了算"。它的判断依据是来源优先级、选择器权重、书写顺序。而继承解决的是"当前元素没有任何规则命中时,值从哪来"。
举一个具体例子:假设你写了div p { color: green }和p { color: red },两个规则都命中了同一个 p 标签,这时看的是选择器特异性,div p 优先级更高,所以是 green,这是层叠。但假设外层 div 写下color: blue,p 自身没有匹配到任何 color 规则,那么 p 直接取 blue,这是继承。
一句话记忆:层叠管"多打一",继承管"上往下传"。它们同时在浏览器的样式计算过程中生效,搞清楚谁负责什么,调试时可以少走很多弯路。
2. 可继承属性分类:从文档流到文本细节的完整图谱
2.1 字体类属性:最典型的继承阵营
字体属性是继承规则最明显的"铁杆阵营",基本全家族都继承。font-family、font-size、font-weight、font-style、font-variant、font-stretch、font-kerning,全都是继承属性。你只要在 body 上写一次font-family: "PingFang SC", "Microsoft YaHei", sans-serif,全站文字就统一了,这可以说是继承带来的最大懒人福利。
这里有个非常核心的细节要单独拎出来:font-size 和 line-height 虽然是继承属性,但继承的方式有讲究。
如果父元素的 font-size 是一个固定值,比如font-size: 16px,那么子元素直接拿 16px 用,这很好理解。但如果你写了font-size: 150%或者font-size: 1.5em,那你实际上是把一个"相对值"先计算成了绝对像素值,再传递下去。比如父元素 16px,子元素声明 font-size: 1.5em,计算后是 24px;而孙元素如果没写 font-size,他并不会继承 1.5em 这个"倍率",而是继承已经算好的 24px 绝对值。这意味着:随着嵌套层级加深,相对字体的倍率并不会继续叠加。
同理,line-height 如果写成百分比或带单位的值,继承下去的就是计算后的像素;但写成无单位数字(比如line-height: 1.5),子元素会继承这个比率,然后基于自己的 font-size 重新计算。官方 W3C 规范一直推荐在 font 复合属性和 line-height 上使用无单位数字,就是为了避免嵌套时出现行高越滚越大的问题。
2.2 文本类属性:不止 color 和 text-align
文本类属性是继承的第二个"大户"。常见的继承属性包括 color、text-align、text-indent、text-transform、text-decoration(注意:text-decoration 在实际渲染中会有一些特殊规则,规范上它是继承属性,但多数浏览器倾向在行内盒上直接传播视觉效果)、text-shadow、letter-spacing、word-spacing、white-space、word-break、word-wrap、overflow-wrap、direction、writing-mode、text-size-adjust、tab-size 等等。
这里我挑几个容易踩坑的说明一下。
text-transform 是继承属性,这意味着如果你在父容器设置了text-transform: uppercase,里面的中文可能没反应(中文本就没有大小写),但所有西文和数字都会悄悄变成大写。我踩过最典型的一次:在做某个数据面板时,给外层 div 加了 text-transform: uppercase 想把英文单位统一,结果列表里所有英文产品名前缀全变成了大写,后来排查了很久才发现是继承在"作祟"。
white-space 同样是继承属性。你可能会想"white-space 决定的是我自己的换行和空格处理,怎么会传染给子元素?"——它确实会。父容器设了white-space: nowrap,下面的标题、段落通通不换行,这在做长文本卡片时是个非常隐蔽的坑。
顺便说一句 vertical-align,这个属性特别有迷惑性。它看起来跟文本排版强相关,很多同学以为是继承的。实际上vertical-align 不是继承属性,它只作用于自身。经常有人在父元素上写 vertical-align: middle 希望所有子元素居中,发现没效果,就是因为这个属性压根不继承。
2.3 列表、表格与其他容易被忽略的继承属性
列表类属性是"低调的继承者"。list-style-type、list-style-position、list-style-image 都是继承属性。在一层层嵌套的 div 里,如果你在某个祖先上设了list-style: none,那么里面所有 ul 的默认圆点都会消失。这个特性也带来一个经典场景:做导航菜单时经常在全局重置里写ul, ol { list-style: none; },就是为了阻断继承链带来的干扰。
表格相关的一些属性也继承了,包括 border-collapse、border-spacing、caption-side、empty-cells、table-layout。最需要注意的是border-collapse 和 border-spacing 在多数浏览器里只对 table(以及 display: table 系列)的自身生效,但对嵌套表格元素确实能继承它的计算值。你可能不会直接意识到这个问题,但如果你给某个表格容器设置了border-spacing: 0,内部多个子表格默认也都是零间距。
还有一些零碎但有用的继承属性:visibility、cursor、quotes、hyphens、orphans、widows、speak、pointer-events(这个属性规范上是继承的,但实际表现中不同浏览器略有差异,建议显式设置)。
visibility 是我特别提醒的:可继承属性,并且它和 display 的继承行为有本质区别。display: none不继承,只是父元素消失连带子元素一起不渲染;而visibility: hidden会继承,子元素如果显式设置visibility: visible,它可以重新显示在父元素的区域里。这个特性在做自定义下拉框、气泡提示时非常好用。
2.4 可继承属性完整速查表
为了方便你日常查阅,我把主要可继承属性整理成一个速查表,贴在下面。这张表基本覆盖了实际开发中会用到的绝大多数场景。
| 大分类 | 属性列表 | 备注说明 |
|---|---|---|
| 字体类 | font, font-family, font-size, font-style, font-weight, font-stretch, font-variant, font-kerning | font 是复合属性,子项基本继承 |
| 文本类 | color, text-align, text-indent, text-transform, text-decoration, text-shadow, letter-spacing, word-spacing, white-space, word-break, word-wrap, overflow-wrap, line-height, direction, writing-mode, tab-size, text-size-adjust | text-decoration 在行内元素的表现有特殊性 |
| 列表类 | list-style, list-style-type, list-style-position, list-style-image | 嵌套列表会自动延续祖先样式 |
| 表格类 | border-collapse, border-spacing, caption-side, empty-cells, table-layout | 实际作用对象有限,但值会继承 |
| 其他 | visibility, cursor, quotes, hyphens, orphans, widows, speak, pointer-events | 按需记忆即可 |
这些属性你不需要死记硬背,唯一要做的是在写样式时建立条件反射:如果这个属性影响的是文字、排版、列表、表格的"外观参数",那么它大概率继承。我做了数年样式开发,这个条件反射比死记灵活得多。
3. 不继承的属性:记住这几个大类就够了
3.1 盒模型全家桶:width、height、margin、padding 等
盒模型属性是"不继承"名单里的最大家族。width、height、min-width、min-height、max-width、max-height、margin、margin-top/right/bottom/left、padding、box-sizing,通通不继承。
它们的逻辑很好解释:每个元素都是独立的盒子,宽度和高度必须根据自身内容、父容器约束和布局环境来独立计算。如果 width 会继承,一个宽度 1200px 的容器里面套一层 div,这个 div 也变成 1200px,再套一层还是 1200px,你根本没有办法做任何响应式布局。所以 CSS 规范把盒模型属性全部设为不继承,这是合理的必然选择。
虽然这些属性不继承,但两个概念容易混淆:width 的百分值和继承没关系。width: 50%是按父容器的计算宽度来计算的,这是"百分比参照",和继承的机制完全不同。很多人把这个搞混,以为是继承了父元素的 width。
另外 margin 和 padding 也有一个容易误导的表现:如果一个父元素设置了 padding,子元素"被推"到右边,看起来像是子元素继承了 padding,其实子元素的 margin/padding 计算值仍然是默认的 0 或 auto。
3.2 定位与布局体系:position、display、flex/grid 相关属性
第二个不继承的大类是布局相关。display、position、top/right/bottom/left、float、clear、z-index、overflow、flex-direction、flex-wrap、flex-grow、flex-shrink、flex-basis、gap、justify-content、align-items、grid-template-columns 等,全部不继承。
display 是这里面最容易混淆的非继承属性。你设置父容器display: flex,里面的子元素并不会继承 display 的 flex 值,它们仍然是原来的块级元素;只不过由于父容器变成 flex 容器,子元素的"display"在格式化上下文里会被重新计算为 flex item,但你打开 Computed 面板看子元素的 display 值,它照样还是 block 或 inline,这个过程叫改变参与的格式化上下文,不是继承。
position 和 top/left 更加直观:如果 position 继承,你把一个子元素 absolute 定位到某个坐标,它的子子孙孙全都跟着 absolute 跑,那网页就完全失控了。float 同理,浮动是"自己脱离文档流"的状态,不可能传给后代。
overflow 也是不继承的,这一点和我们在 2.2 节里讲的 white-space 刚好形成对比。white-space 控制换行行为,它继承了;overflow 控制溢出内容怎么处理,它不继承。所以你经常要在一个滚动区域里对每个子层写明 overflow: hidden 或 overflow: auto,不能只在外层设一遍了事。
3.3 背景、边框、阴影、圆角等视觉修饰属性
第三类不继承的是背景和边框相关。background 及其全部子属性(background-color、background-image、background-position、background-size、background-repeat、background-clip 等)、border 和它衍生的所有子属性、box-shadow、border-radius、outline,通通不继承。
这同样不难理解:如果 background-image 继承了,一个容器里所有子元素都背上同一个背景图,那个画面可以说是灾难。边框假如会继承,父容器设了 1px solid red,每个子元素四周都出现红框,等于每个元素都被框起来,视觉上完全不可用。
不过我要补充一点细节:虽然背景不继承,但默认值是 transparent。父元素有背景色时,子元素因为自己是透明背景,"看起来"像是继承了父级的背景,实际上是子元素露出了父元素那一层底色。同理 border 默认是 medium none color,父元素的边框颜色在子元素未设置时并不会传递;你只有在子元素自己设置了 border style 后,border-color 的默认值才是 currentColor,而 currentColor 会从 color 继承值推演,这里有一个间接关联,不要被表象迷惑。
3.4 常见的不继承属性快查表
| 大分类 | 属性列表 | 常见迷惑点 |
|---|---|---|
| 盒模型 | width, height, min/max-width/height, margin, padding, box-sizing | 百分比参照不是继承 |
| 布局 | display, position, top/right/bottom/left, float, clear, z-index, overflow, flex 系列, grid 系列, gap | flex item 的计算含义不是继承 |
| 背景边框 | background 系列, border 系列, box-shadow, border-radius, outline | transparent 底色造成的"假继承" |
| 定位修改 | transform, opacity(注意),filter, backdrop-filter | opacity 实际会创造层叠上下文,连带影响渲染效果 |
| 表格内容 | vertical-align, border-spacing 之外的表格独有属性 | vertical-align 极易被误判为继承 |
为什么我把 opacity 和 transform 也放进这个表格?因为它们严格来说不是继承属性,但它们的渲染结果对子元素有"整组影响"。opacity: 0.5会让整个子树变半透明,transform: scale(0.8)会让整个子树缩小,从视觉上非常像继承了。实际上它们是作用于当前元素并连带渲染子树,方向和"继承"不同。如果子元素自己写 opacity: 1,也救不了父级带来的半透明效果——这一点在日常开发中经常让人发疯,我后面还会详细展开。
4. 控制继承的四个 CSS 关键字和实战策略
4.1 inherit 和 initial:一正一反两个极端
当我们搞清楚了属性默认是否继承,接下来就是主动干预了。CSS 为每一个属性都提供了多个"全局关键字",最重要的四个分别是 inherit、initial、unset、revert。
inherit 的意思最好理解:利用这个值,你可以强迫一个本来不继承的属性去继承父元素的值。典型场景是 a 标签。默认情况下 a 标签的 color 不受祖先 color 的影响(浏览器 UA 样式表给 a 定义了蓝色并带下划线),这在很多设计系统里,我们希望"所有链接跟随正文颜色走",于是我们经常写:
a { color: inherit; text-decoration: inherit; }这两行写下去,链接就乖乖融入段落了。另一个比较实用的 inherit 场景是 button 的字体。大多数浏览器的 button 默认不会继承父级 font-family,如果你要让按钮视觉上跟正文一致,最简单的方式就是button { font: inherit; }。
initial 则是把属性值重置为 CSS 规范定义的初始值,它和浏览器 UA 样式表无关。比如color: initial就是黑色(规范初始值是 CanvasText 或黑色),display: initial就是 inline,而不是很多人以为的 block。这个关键字非常适用于"我想把某个组件的所有样式回归默认再看一眼"的场景。
4.2 unset、revert 和它们的区别
unset 是一个上下文敏感的关键字:如果属性是可继承属性,unset 等价于 inherit;如果属性是不可继承属性,unset 等价于 initial。这样可以很方便地写一条规则去"清除"之前的干扰。例如:
.card * { color: unset; }这条规则会把 .card 内所有元素的 color 重置为"重新参与继承链",也就是说,它们都会去继承 .card 的 color,之前的各种针对性声明全部失效。对于可继承属性,这招是打破全局污染的有效工具。对于不可继承属性,unset 则把属性打回初始值。
revert 是几个关键字里最微妙的一个。它把属性值回退到"源级别"的样式:如果是作者样式(我们自己写的 CSS),就回退到用户代理样式(浏览器默认样式);如果在浏览器 UA 内部使用,则回到该样式表的上一个来源。revert 最典型的应用场景是:你想去掉自己写的样式,回到浏览器原生样式的表现。一款页面组件里,你不想再用别人定义的 heading 样式,直接:
h2 { all: revert; }这里顺带引入 all 这个属性。all: unset、all: inherit、all: initial可以一次性作用于所有属性,非常省事。all: revert可以快速把组件所有样式降级为浏览器默认,在很多"清理全局样式污染"的场合极其好用。
4.3 实际工作中的继承管理策略
光知道上面四个关键字还不够,管理继承最关键的是要建立"继承边界"的思维。
我给你一个实操建议:在做大型组件库或者业务系统时,单独定义一个 reset 文件,在最外层阻断可继承属性的意外传递。比如全局强制文字相关属性:
body, button, input, select, textarea { color: inherit; font: inherit; }这一行几乎是所有现代 CSS 重置方案(normalize 里改良版)的标配。button 和 input 的 font 不继承,这是我们从第 3 节里获得的结论;为了统一跨浏览器表现,必须用 inherit 把它拉回继承链中。
再举一个继承管理的实战:设计一个页签组件,页签内部所有文字必须有统一的间距和排版,但页签外面又套在一个 color 会被动态切换的主题容器里。这时最好不要在页签里用一堆 initial、revert 去做隔离,而是直接用all: initial把页签内部的所有可继承属性断干净,然后在页签根节点重新声明你需要的基准值。这样做的可控性远超"遇到一个属性改一个"。
控制继承的四关键字全部列出来,用的时候最忌脑子一热滥用,只针对你确定要被影响的元素和属性使用,否则很容易把布局搞崩。
5. 实战演示:一个常见的"字体继承失效"问题
5.1 场景重现:button 里的字体为什么变回去了
假设你在做一个表单页面,在 body 里统一设置了:
body { font-family: "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; color: #333; }结果整个页面的文字都正常,唯独按钮和输入框的字母、数字看起来还是"系统字体",字号似乎既不是 14px 也不是初始值。问题出在哪?
答案是:绝大多数浏览器的 UA 样式表里,button、input、select、textarea 都有一条独立的 font 声明,它们的 font-family 默认是 system-ui / -apple-system 之类的系统字体,font-size 默认值也非浏览器根字号继承值。由于这些是"用户代理样式",权重最低,理论上我们写在 body 上的规则应该能覆盖它们。但我们的选择器是body,而 UA 里按钮的 font 规则指定在 button 元素上,从层叠的角度来看,写在元素自身上的 UA 规则优先于继承来的值——即使继承链里 body 给了 font-family,但在 button 自己这个节点上,UA 样式表声明比继承值优先级更高。
解决方式非常简单:
button, input, select, textarea { font: inherit; color: inherit; }这一行把表单控件的 font 拉回继承链。你会发现很多第三方 CSS 库(Bootstrap、Tailwind Preflight)都在这么做,原理就在这里,不是什么玄学。
5.2 场景再现:a 标签的 color 为什么无视父级颜色
有一个设计需求:页面正文颜色是深灰色,链接要跟随正文颜色,而不是默认蓝色。此时直接在父级上等于是等不到结果的,因为浏览器给 a 标签署了"专属 UA 样式"。
解决方案:
a { color: inherit; text-decoration: none; }这样 a 标签的颜色就跟随祖先链上的 color 了。如果你希望链接在 hover 时变成主题色,因为继承性,你可以直接在祖先上写:hover { color: ... }并配合子孙选择器,也可以针对 a 单独写一条,两者并不冲突。
5.3 场景再演:只想垂直居中,vertical-align 为什么没效果
我再举一个高频误用案例。想在一个 div 内把一个 inline-block 元素垂直居中,在 div 上写了:
.container { vertical-align: middle; }结果元素纹丝不动。原因不再赘述:vertical-align 不继承,只作用于当前元素,而且它实际作用的对象是"行内级元素与表格单元格内容"的对齐方式。对块级容器设置 vertical-align 基本不会有任何效果。正确做法是给那个 inline-block 子元素本身设置vertical-align: middle,且父元素需要是 line box 环境,或者改用 flex 的 align-items。
这三个场景本质上都指向同一个道理:遇到没生效的属性,先问自己三个问题——它是不是被覆盖了?它是不是不继承?它是不是作用于自身而不是父级?定位清楚,排查时间能缩短一大半。
6. 继承相关经典坑位排查与避坑心得
6.1 经典坑位一览表
| 坑位现场描述 | 根因 | 解决办法 |
|---|---|---|
| body 设置了全局 font-family,button/input 的字“不一样” | button、input 等标签自带 UA 字体样式 | 用font: inherit或 reset 文件统一处理 |
| 父级设了 color: #333,a 标签仍是蓝色 | 浏览器 UA 样式表给 a 定义了默认颜色,其优先级高于继承值 | a { color: inherit; } |
| 父级设 overflow: hidden,子元素却照样溢出 | overflow 不继承 | 在需要裁剪的元素上单独设置 overflow |
| 父级设 white-space: nowrap,子元素全都不换行 | white-space 是继承属性 | 需要换行的子元素单独设white-space: normal |
| 父级设 line-height: 1.5,嵌套多层后行高越来越大 | line-height 无单位值以比率形式继承,且会在子级基于 font-size 重算 | 对嵌套子元素显式设置 line-height 或使用固定单位 |
| opacity: 0.5 后里面一整个区域半透明,子元素设置 opacity: 1 也没用 | opacity 不继承但作用于整个渲染组 | 改用 background-color: rgba 或单独处理透明度场景 |
| 兄弟元素都绑了 cursor: pointer,父级设的 cursor 不起作用 | cursor 是继承属性,但更内层的声明会覆盖 | 找到覆盖来源,不合适的就在更深节点覆盖回来 |
| 设置了 list-style: none 的 ul 内部嵌套 ul,内层小圆点消失 | list-style 可继承 | 内层 ul 单独设置 list-style-type |
6.2 用 DevTools 提高排查继承问题的效率
搞 CSS 继承排查,绝对离不开浏览器开发者工具。我推荐一个固定操作序列:先选中目标元素,切到 Computed(计算样式)面板,然后打开"继承自"来源分组。Chrome 和 Edge 的 Computed 面板会在每个属性旁标注这个值是来自 inherited from 某个元素,还是来自自身匹配的规则,还是来自浏览器 UA。
具体操作流程是:
- 右键检查目标元素,切到 Computed 面板。
- 在面板里搜索你要追查的属性名,比如 color,看它的来源。如果显示"inherited from div.parent",就证明继承自这个父级,你再去这个父级看 color 有没有被覆盖。
- 如果来源显示"user agent stylesheet",说明是浏览器默认样式在起作用,你需要在作者样式表里用更高的优先级或直接写在元素上。
- 再有一个进阶技巧:在 Styles 面板里选中一个元素,按键盘上下方向键可以快速遍历同一选择器组内的任意元素,配合"继承自"的层级,可以一层层往上追踪来源。
这个方法我用了几年,比凭感觉猜要可靠得多。尤其是遇到多个嵌套容器、多个层叠规则叠加时,用 DevTools 的 Computed 面板能看到"最终打赢的那条规则到底是谁",直接解决大量无头悬案。
6.3 几个我验证过多次的开发习惯
日常开发中,我总结了几个和继承相关的实用习惯。
第一,全局 reset 不如全局"继承归位"来得实用。与其在 reset 里把每个标签默认样式删干净,不如对 button、input、a 这些"脱离继承链"的元素主动拉回继承值:
button, input, select, textarea, a { font: inherit; color: inherit; }这会大幅减少统一样式的重复劳动,也能保证组件的可复用性。
第二,显式声明边界。组件的根节点最好把color、font-size、line-height写明确,避免被上层主题或者全局样式污染。如果你做的是一个暗色主题的弹窗组件,弹窗内部的内容可能因为继承链从外层拿到深色文字的 color,打开一看直接看不清,这个问题尤其容易出现在弹窗、抽屉、工具提示这类 DOM 位置靠后的组件里。
第三,Styled Component 和 CSS Modules 环境下也要注意继承。虽然 CSS 被模块化,但继承是渲染期的行为,跟打包方式无关。模块化了你照样会被继承链影响。比如组件 A 在根节点写了font-size: 12px,组件 B 嵌套在组件 A 下,B 的所有文字默认继承 12px,除非 B 自己显式设置 font-size。所以组件的"边界设计"不要只停留在视觉上,还要考虑继承链的边界。
第四,revert 是复杂系统中的逃生舱。在老旧项目里,全局样式渗透、类名冲突满地都是,你想让某个卡片"回到浏览器最原始的样子",直接all: revert往往比一条条覆盖快得多。但注意 revert 不支持 IE,如果你还在维护老古董浏览器,就用 unset 或 initial 代替,具体取舍以业务场景为准。
7. 写 CSS 时的继承视角:选价值、设基准、断污染
7.1 用继承视角组织全局变量和样式
现代 CSS 开发离不开自定义属性(CSS Variables),我格外建议把"继承视角"应用到变量设计上。自定义属性本身就是继承的:你在 :root 定义的--primary和--font-base,全站的任意元素都能读取,包括内部组件。这既是便利也是风险,因此我会习惯给不同主题组件命名独立的变量前缀,例如--card-primary,用它隔开业务组件的继承域。
7.2 继承是"最小化副作用"的工具
最后想把一个日常心得放这里,和初学者共勉。你在排查样式问题时,遇上一个"莫名奇妙"的样式,不要上来就直接找一条针对性规则去覆盖。你要先想:这个值是从哪来的?是继承来的,就找源头;是 UA 来的,就重写默认;是层叠覆盖来的,就调整权重。每一步都用这个思路去走,你的样式代码会越来越干净,不会出现一堆"打补丁"式的规则。继承没有魔法,它只是层叠样式表里最基础但最容易忽略的机制。
多花半小时把这几张表吃透,你在开发里省下的可不只是半天。以后遇到"为什么没继承""为什么突然继承了"的问题,你可以直接打开这篇文章对应的表格,对号入座。实践出真知,在我看来,把 CSS 继承这件事搞明白,比背一百条选择器语法更能提升生产力。