浏览器按层叠机制淘汰规则而非协商解决冲突;三步淘汰:先筛掉同源中优先级更低的!important声明,再按来源分组(用户代理、用户、作者样式)。

浏览器不“解决”冲突,它只是按固定规则选一条生效——层叠机制本质是淘汰制,不是协商制。
层叠顺序决定谁先被淘汰
当多条规则命中同一元素的同一属性,浏览器按三步淘汰:
- 第一步筛掉所有
!important声明中优先级更低的(注意:!important只在同源内比权重) - 第二步按来源分组:用户代理样式(浏览器默认)
- 第三步在作者样式内,按声明顺序(后写的覆盖前写的)+ 选择器特异性(
(a,b,c,d))共同判定
关键点:层叠不是“融合”,而是单向覆盖。比如 .btn { color: blue; } 和 .btn.primary { color: red; } 同时存在,后者胜出不是因为它“更强”,而是它的特异性 (0,0,2,0) 高于前者 (0,0,1,0)。
@layer 只改层间顺序,不碰层内胜负
写了 @layer components, overrides; 并不能让你的 .btn 盖过第三方的 .ant-btn ——除非两者都在同一层,或你明确把第三方样式收进 @layer components,再把自定义样式放 @layer overrides 里。
立即学习“前端免费学习笔记(深入)”;
-
@layer声明必须在 CSS 文件最顶部,前面不能有任何其他规则(包括注释也不行) - 第三方库如未自带
@layer,需用@import url("xxx.css") layer(components);手动包裹 - 层内规则仍按特异性 + 顺序决胜,
@layer overrides { .btn { color: green; } }若特异性不够,照样被.ant-btn.ant-btn-primary((0,0,2,0))压住
伪类状态容易踩坑的优先级陷阱
:hover、:disabled 这类伪类和普通类选择器权重相同(都是 c 位),谁在后面谁赢——但这个“后面”指最终编译后的 CSS 字节流位置,不是你在 Less/Sass 里写的顺序。
- 避免混用:
.btn:hover和.btn.is-disabled优先级一样,加载顺序稍有变动就失效 - 推荐统一转为类组合:
.btn.is-hovered、.btn.is-disabled,所有规则都是两个类,权重一致且可控 - 若必须用伪类,至少保证它和对应类在同一文件、相邻声明,比如:
.btn.is-active { ... }紧跟.btn:active { ... }
命名空间类名才是最稳的隔离手段
与其反复调优 @layer 或算特异性,不如让类名自带作用域。比如 user-card-title 几乎不可能和 product-list-title 冲突,也不依赖 HTML 结构嵌套。
- 禁用纯语义名:
title、list、button—— 它们在项目里大概率重复出现 - 拒绝多层嵌套:
.sidebar .item .label看似精准,但 DOM 微调就断,且实际生成的是后代选择器,易误匹配 - 第三方组件也封装一层:
ui-button-primary而非直接用.el-button,既复用能力又守住边界
真正难的不是写对某一条规则,而是让每条规则从诞生起就清楚自己该影响谁、不该影响谁。层叠机制只是裁判,而类名设计才是赛前报名表——填错名字,再高超的技巧也上不了场。


















