样式不生效主因是选择器权重不足,需通过DevTools查看带删除线样式及specificity四元组(a,b,c,d),逐位比较而非相加;提升权重应优选精准限定、属性选择器或CSS Modules,避免!important和@import。

样式不生效,八成不是写错了,而是你的选择器在权重比拼中输了——浏览器只认 specificity 四元组,不认你写的有多认真。
怎么看哪条规则赢了?
打开 DevTools(F12),选中元素,在 Styles 面板里找带删除线(strikethrough)的样式。鼠标悬停上去,会显示 specificity is lower than another rule,并附带一个四元组,比如 0,1,1,0:
- ID 选择器(如
#header)贡献 b=1(即 100) - 类 / 属性 / 伪类(如
.btn、[disabled]、:hover)各算 c=1(即 10) - 标签 / 伪元素(如
div、::before)各算 d=1(即 1) - 内联样式(
)是 a=1(即 1000),基本不用管
注意:四元组不能加总,必须逐位比较。只要对方 b 位是 1,你写十个类也赢不了。
为什么加了类还是被盖?常见权重误判
你以为 .card .title(c=2)很稳,但可能输给 .modal .header h2(c=2, d=1 → 总权重更高);你以为 article ul li a(d=4)很强,其实远低于 #user-list .item(b=1 → 权重 100)。
立即学习“前端免费学习笔记(深入)”;
-
:not(.active)的权重等同于.active,别以为它“弱” -
.dialog .footer和.dialog > .footer权重相同,但后者匹配更稳,不易被意外嵌套干扰 - 第三方库(如 Ant Design)常用
.ant-btn-primary这类双类名,权重是0,0,2,0,单写.btn-primary(0,0,1,0)必输
怎么安全提权?别碰 !important
!important 不改变权重值,只强制插队;一旦用了,后续覆盖必须也加,容易陷入恶性循环。真正该做的是让选择器更准、更可控:
- 用子选择器替代空格:
.card > .title比.card .title更明确,权重不变但匹配更稳 - 加一层有意义的父级限定:
.app-layout .btn-primary把权重从0,0,1,0提到0,0,2,0,且语义清晰 - 用属性选择器兜底:
[data-role="tooltip"]权重 =0,0,1,0,和类持平,但几乎不会被第三方样式意外覆盖 - Vue/React 中 CSS Modules 或
<style scoped>会自动加哈希后缀,你写的.btn实际匹配不到真实 DOM,得用编译后的类名或改用[data-v-xxx]属性选择器
框架样式覆盖时,加载顺序和作用域才是关键
Laravel Blade 里忘了在布局中写 @yield('styles'),或者自定义 CSS 放在了 Bootstrap <link> 前面,都会导致样式失效——即使权重一样,后加载者才赢。
- 确保自定义样式
<link>放在第三方 CSS 之后 - 避免用
@import,它解析滞后,容易打乱预期顺序 - 用
:where()包裹高权重选择器可归零特异性,比如:where(.dashboard.card.header) .button的权重坍缩为.button的0,0,1,0,让你轻松覆盖
最常被忽略的一点:权重计算不看 DOM 深度,而看选择器结构本身;你写的 div .title 在 Vue scoped style 下根本没机会匹配,因为真实 DOM 是 div[data-v-abc] .title[data-v-abc] —— 这时候再堆类名也没用,得换思路。


















