浏览器按三步淘汰制解决CSS冲突:先筛同源中特异性更低的!important声明,再按来源分组(!important>作者>用户>用户代理),最后在同源无!important规则中比对特异性(a,b,c,d)并依声明顺序决胜。

浏览器不“解决”冲突,它只按固定淘汰顺序选一条生效——优先级冲突本质是单向覆盖,不是协商或融合。
层叠三步淘汰制:先筛来源,再比权重,最后看顺序
当多个规则命中同一元素的同一属性(比如 color),浏览器执行严格三步淘汰:
- 第一步:剔除所有同源中
!important声明里特异性更低的(注意:!important只在同源内比权重,跨源不参与比较) - 第二步:按来源分组排序,从高到低为:
!important声明 > 作者样式(你写的 CSS) > 用户样式 > 用户代理样式(浏览器默认) - 第三步:在同源且都无
!important的作者样式内,才进入特异性比较;若特异性相同,后声明的规则胜出
特异性计算不是加法,而是四位数逐位比大小
特异性写作 (a,b,c,d),不是把数字相加得出总分,而是像比较 IP 地址一样从左往右比:
-
a:内联样式存在即为1,否则0(<p style="color:red">) -
b:ID 选择器个数(#header算 1,#nav #menu算 2) -
c:类、属性、伪类个数(.btn、[type]、:hover各算 1) -
d:元素、伪元素个数(p、::before各算 1)
例如:#user .profile.active::before 是 (0,1,2,1),而 .user-card .title 是 (0,0,2,0) ——前者胜出,因为 b=1 > b=0,后面两位根本不用比。
立即学习“前端免费学习笔记(深入)”;
@layer 不改特异性,只调换层间出场顺序
@layer 是层序开关,不是权重放大器:
-
@layer base, theme, overrides;必须写在 CSS 文件最顶部,前面不能有任何内容(包括注释) - 第三方库没用
@layer?得用@import url("lib.css") layer(base);手动包裹,否则它仍按普通作者样式参与层叠 - 层内规则依然遵守原有特异性 + 顺序规则:
@layer overrides { .btn { color: red; } }若特异性低于.ant-btn-primary((0,0,2,0)),照样被压
伪类和类权重相同,但“后面”指最终 CSS 字节流位置
:hover 和 .is-hovered 都属于 c 位,权重一样。但谁赢取决于最终生成的 CSS 中谁更靠后:
- 如果你用 Less/Sass 写了
.btn:hover在 A 文件,.btn.is-active在 B 文件,而 B 被@import在 A 后面,那.btn.is-active就赢 - 但构建工具或打包顺序稍有变动,结果就翻转——这正是线上偶发样式失效的常见原因
- 推荐统一用命名空间类:
ui-button--hovered,避免依赖加载时序
真正难控的从来不是计算公式,而是特异性相同却因构建顺序、@import 位置、甚至 CSS 压缩工具删空行导致的隐性覆盖。别迷信“算对了就稳”,要让类名自带作用域,让层叠路径可预测、可审计。


















