
彻底搞懂CSS优先级:为什么我的样式没有生效?
📷 Negative Space / Pexels彻底搞懂CSS优先级:为什么我的样式没有生效?
CSS优先级是前端开发必须掌握的核心概念。本文详解(A,B,C)计算规则、常见误区,以及如何用优先级计算工具快速排查样式冲突。
每个前端开发者都遭遇过这种挫败感:明明是正确的CSS规则,在浏览器里就是不生效。打开DevTools一看,自己写的规则被划了删除线,被另一条不知道从哪来的规则覆盖了。
于是第一反应是加上!important。
问题是,这只是把炸弹埋得更深。半年后,代码库里到处都是!important,没人敢动,一改就出问题。
CSS优先级的规则其实并不复杂,只是需要一次认真的梳理。掌握了它,你就能真正理解样式冲突的根源,而不是靠!important强行压制。
(A, B, C) 三列计算法
CSS优先级不是一个单一数字,而是由三列数字组成的值(A, B, C),比较时从左到右逐列进行。
A列:ID选择器
#header、#main等ID选择器计入A列,每个贡献(1, 0, 0)。这一列的存在,是现代CSS实践中不推荐用ID选择器写样式的根本原因——一旦用了,覆盖起来非常麻烦。
B列:类选择器、属性选择器、伪类
类选择器(.nav)、属性选择器([type="text"])、伪类(:hover、:focus、:nth-child()),每个为B列加1。
C列:元素选择器、伪元素
div、p、ul等元素类型选择器,以及::before、::after等伪元素计入C列。
不计入优先级的内容
通配符选择器*、子代选择器>等组合器、以及:where()不影响优先级。
示例对比
/* (0, 0, 1) */
p { color: red; }
/* (0, 1, 0) */
.intro { color: blue; }
/* (0, 1, 1) */
.intro p { color: green; }
/* (1, 0, 0) */
#main { color: orange; }
/* (1, 1, 1) */
#main .content p { color: purple; }
若以上规则同时作用于同一元素,(1, 1, 1)最高,最后一条规则生效。
常见误解
误解一:选择器越长越具体,优先级越高
长度不等于优先级。.nav .list .item a.link看起来很精确,但优先级只有(0, 3, 2),遇到#header的(1, 0, 0)直接输。
误解二:后写的样式一定覆盖前面的
只有当优先级完全相同时,写在后面的才胜出。如果优先级不同,不管顺序如何,高优先级的总是赢。
:is()、:not()、:where()的特殊处理
:not()会继承参数的优先级。:not(.hidden)因为.hidden的存在,优先级是(0, 1, 0)。
:is()取参数列表中优先级最高的那一个。:is(#main, .nav, p)因为#main,整体优先级是(1, 0, 0),即使实际匹配的是.nav元素。这个行为让很多开发者感到意外。
:where()永远是0。在设计基础样式库时,把选择器放进:where()是一种让使用者能轻松覆盖的好习惯。
实战场景:覆盖第三方组件库样式
这是实际项目中最常见的优先级冲突场景:
/* 组件库的CSS */
.ui-btn.ui-btn--primary {
background-color: #0066cc;
}
/* 自定义覆盖 */
.my-button {
background-color: #ff5500;
}
组件库:(0, 2, 0),自定义规则:(0, 1, 0),自定义样式输了。
解决方式:
- 重复类名:
.my-button.my-button,优先级变成(0, 2, 0),打平 - 加父级上下文:
.app-wrapper .my-button,同样是(0, 2, 0) - !important:真正万不得已时再用
使用CSS优先级计算工具
CSS优先级计算工具可以让你粘贴选择器后立即看到(A, B, C)的详细分解,不用在脑子里手动计算。
适合使用的场景:
- 调试样式冲突时,把两条竞争规则放进去对比,立刻知道谁该赢
- 写复杂选择器时先检查一下,确保优先级符合预期
- 学习阶段:边改选择器边看数字变化,是理解优先级最直观的方式
工具的局限性
对常规选择器计算准确。复杂嵌套的:is()表达式以及Shadow DOM相关选择器(::slotted()、::part())在边界情况下可能不够精确。精度要求高时,以浏览器开发工具为准。
写出低优先级CSS的最佳实践
样式不要用ID选择器 ID保留给JavaScript钩子和页面锚点,CSS中统一用类选择器,保持优先级可控。
选择器尽量短
.btn-primary比.page .sidebar .nav .btn-primary更好,优先级更低,也更不容易因标签结构变化而失效。
采用BEM或类似命名规范
.card__title--featured这种写法让每个元素都能用单一类名精准定位,保持(0, 1, 0)的统一优先级层次。
!important只留给工具类
.hidden、.visually-hidden这类必须始终生效的工具类是!important的正确用途。其他情况用!important往往意味着设计问题。
相关工具
- CSS转Tailwind工具 — 将已有CSS转换为Tailwind类名
- CSS压缩工具 — 清理和压缩CSS代码
- CSS Flexbox生成器 — 可视化生成弹性布局代码
CSS优先级是一个一旦真正理解就会受益长久的基础知识。它让你和浏览器站在同一边,而不是不断对抗它。使用CSS优先级计算工具来辅助调试,同时把规则内化到日常写CSS的习惯中,你会发现样式冲突越来越少,代码越来越清晰。