样式不生效主因是特异性(specificity)权重不足而非书写顺序,浏览器按四元组(a,b,c,d)逐位比较:内联样式、ID、类/属性/伪类、标签/伪元素数量,高位大者胜出。

特异性(specificity)比顺序更关键
后面写的 CSS 规则不生效,大概率不是因为“写在后面”,而是它的选择器权重 specificity 比前面的低。浏览器不是按顺序“后写赢”,而是先算四元组 (a,b,c,d):内联样式数、ID 数、类/属性/伪类数、标签/伪元素数,逐位比较,大者胜出。
常见陷阱包括:
-
.btn(权重0,0,1,0)输给button.btn(0,0,2,1),哪怕后者写在前面 -
#app .card .title(0,1,2,1)天然压制你写的.title--primary(0,0,1,0) -
div[data-role="header"]和.header权重相同,但前者语义明确、不易被意外覆盖
DevTools 里被划掉的规则到底在说什么
打开 Chrome DevTools → Elements → 选中元素 → 右侧 Styles 面板中带删除线(strikethrough)的规则,就是被覆盖的。鼠标悬停会提示 “This rule was overridden by …”,重点看三处:
-
Specificity:显示为0,1,1,2这类数字,确认是不是你自己的规则数值更低 -
Source:点文件名跳转,确认是不是另一处同名类(比如组件库或同事代码)悄悄覆盖了 - 有没有
!important:它不参与 specificity 计算,但会让该声明“插队”,也容易引发连锁加!important
@import 和 的加载时机不改变优先级本质
@import 只是把外部 CSS 内容“粘贴”进当前样式表,不创建新层叠上下文,也不提升优先级。它甚至必须写在 <style> 最开头,否则整条语句被忽略。
立即学习“前端免费学习笔记(深入)”;
真正影响最终结果的是所有规则合并后的统一排序——浏览器收集完全部样式(含 @import、<link>、<style>、内联 style 属性),再按 specificity + !important + source order 综合判定。
所以别纠结 @import 放哪,先检查它引入的内容里有没有更高权重的选择器。
框架 scoped 样式让“看起来一样”的选择器根本匹配不上
Vue 的 <style scoped> 或 React 的 CSS Modules 会在编译时给选择器自动加哈希属性,比如 .card .title 实际变成 .card[data-v-abc123] .title[data-v-abc123]。
这意味着:
- 你在全局 CSS 里写的
.card .title,根本不会命中 scoped 组件内的元素 - JS 动态插入的样式若没同步带上
data-v-abc123,也会失效 - 想覆盖 scoped 组件样式,要么用
::global(.card)(Vue),要么改用 CSS Modules 的:global显式声明
最易被忽略的一点:权重计算照常进行,但匹配失败就直接出局——连比 specificity 的资格都没有。


















