CSS 层叠与优先级:我的样式为什么不生效
CSS 层叠与优先级:我的样式为什么不生效
写 CSS 最挫败的时刻:明明写了样式,页面上就是不生效。打开 DevTools 一看,自己的规则被划掉了,上面盖着一条不知道从哪来的。这背后就是 CSS 的"C"——层叠(Cascade)。
层叠的三道裁判
两条规则冲突时,浏览器按这个顺序裁决:
- 来源与重要性:
!important> 作者样式 > 浏览器默认样式 - 优先级(Specificity):同来源比选择器权重
- 书写顺序:权重一样,后写的赢
日常 90% 的"不生效"都卡在第 2 关。
优先级的计算规则
把选择器拆成四档(a, b, c, d),从高到低:
| 档位 | 内容 | 例子 |
|---|---|---|
| a | 行内样式 | style="color: red" |
| b | ID 选择器 | #nav |
| c | 类、属性、伪类 | .btn、[type="text"]、:hover |
| d | 元素、伪元素 | div、::before |
比较方式是从高档往低档逐级比,高档赢了直接结束:
/* (0,1,0,1) #nav 一个 ID + li 一个元素 */
#nav li { color: red; }
/* (0,0,10,2) 十个类也赢不了一个 ID */
.a.b.c.d.e.f.g.h.i.j div span { color: blue; }
第一条赢。权重不进位,10 个 c 也顶不上 1 个 b,这就是为什么不推荐滥用 ID 选择器写样式——一旦用了 ID,后面想覆盖只能再写更长的 ID 组合或者 !important,开始军备竞赛。
几个容易搞错的:
*、组合符(>、+、空格)权重为零,不参与计算:not()、:is()本身不算权重,但括号里的参数算:where()是特例:整个选择器权重恒为零,UI 库用它提供可被轻松覆盖的默认样式
!important:掀桌子
.text { color: green !important; }
加上就赢过所有普通声明,行内样式也压不住。唯一能干掉 !important 的是另一个权重更高的 !important——所以它是单行道的尽头,用了就回不了头。
合理的使用场景基本只有:覆盖第三方组件库的行内样式这种你控制不了来源的情况。自己的代码里出现 !important,多半是优先级设计出了问题,应该从选择器结构上解决。
实战排查套路
样式不生效时按这个顺序查:
- DevTools 看元素,找到被划掉的那条规则,看赢它的是谁、权重多少、来自哪个文件
- 检查选择器是不是没选中——类名拼写、层级对不上(这种 DevTools 里根本不会出现这条规则)
- 检查属性本身是否有效:比如给行内元素设 width/height、值写错单位,规则在但声明被丢弃(DevTools 里会有黄色警告图标)
- 检查是不是被继承值骗了:color 会继承,background 不会,别搞混
工程上的建议
- 统一用类选择器(BEM 之类),让所有规则权重保持在同一档,覆盖顺序只由书写顺序决定,可预测
- 组件库里用
:where()包默认样式,业务方一个普通类就能覆盖 - 禁止 !important 进代码规范,除非注释说明在覆盖第三方
- 嵌套不要太深,三层以内,既是为性能也是为权重可控
层叠机制是 CSS 的设计精髓而不是缺陷,它让样式可以分层组织:库提供默认、主题做覆盖、业务做定制。觉得它"玄学",通常只是还没看清三道裁判的顺序。
看到这里了?如果这篇文章帮到过你
请我喝瓶可乐就好 🥤

评论0 条
还没有评论,来抢沙发~