本文深入解析 CSS 选择器特异性(specificity)机制,阐明为何 h1 元素的 font-size: 36px 始终生效,而父容器 main { font-size: 2rem } 无法通过继承覆盖它——关键在于选择器权重差异与继承规则的本质区别。
本文深入解析 CSS 选择器特异性(specificity)机制,阐明为何 `h1` 元素的 `font-size: 36px` 始终生效,而父容器 `main { font-size: 2rem }` 无法通过继承覆盖它——关键在于选择器权重差异与继承规则的本质区别。
在您提供的 HTML 和 CSS 示例中,<h1> 的字体大小始终为 36px,无论 h1 和 main 的 CSS 规则声明顺序如何调换。这并非因为“后定义覆盖前定义”,而是由 CSS 特异性(Specificity) 和 继承(Inheritance) 两大核心机制共同决定的。
首先纠正一个常见误解:答案中称“两者特异性相同”是不准确的。实际上:
h1 是元素选择器 → 特异性值为 0,0,1(即 (0,0,1))main 同样是元素选择器 → 特异性值也为 0,0,1
✅ 单看选择器类型,二者特异性确实相等。但关键在于:它们作用的目标不同,且 font-size 的应用方式截然不同。
main { font-size: 2rem } 并没有直接设置 <h1> 的字体大小,而是设置了 main 元素自身的字体大小,并将其作为计算继承值的基准。<h1> 是否继承该值,取决于其自身是否声明了 font-size:
h1未声明font-size → 它将继承main 的 2rem(此时 2rem 相对于 main 的父元素字体大小计算,通常为 32px);h1已声明font-size: 36px → 此声明直接作用于自身,特异性生效,完全无视 main 的继承上下文。✅ 因此,h1 { font-size: 36px } 是一条直接、明确、高优先级的样式声明,它覆盖的是 h1 自身的属性,而非与 main “竞争”同一个样式目标。
您交换 main 和 h1 规则顺序后结果不变,正是因为:
main 设置自身字体大小,h1 设置自身字体大小);h1 的样式由 h1 选择器独立控制,main 的样式不会“强制重写” h1 的 font-size,除非使用更高级机制(如 !important 或更高特异性选择器,例如 main h1)。若希望 main 内部的 h1 统一采用 2rem,应直接选中目标元素:
main h1 {font-size: 2rem; /* 特异性:(0,0,2) —— 高于单独的 h1 */}h1 {font-size: 36px; /* 此规则将被上面的规则覆盖(因特异性更高)*/}
此时,<h1> 字体将变为 2rem(约 32px),证明真正起效的是更精确的选择器路径,而非声明顺序。
font-size 是可继承属性,但子元素显式声明会完全屏蔽继承值;font-size 的来源(inline / stylesheet / inherited from main),并点击右侧箭头定位具体规则。<h1> 显示 36px 的根本原因,不是“h1 写在后面”,也不是“main 和 h1 特异性相同”,而是:
? h1 { font-size: 36px } 是对 <h1> 的直接样式声明,具有最高执行优先级;
? main { font-size: 2rem } 仅设置自身字体,其值仅作为继承源头存在,无法覆盖子元素的显式声明;
? 若要实现父控子效果,必须使用组合选择器(如 main h1)提升特异性,或移除子元素的显式声明以启用继承。
掌握这一逻辑,即可精准掌控 CSS 样式流向,告别“为什么没生效”的困惑。