@layer能终结!important滥用,因其将优先级从随机博弈变为可声明、可预测的顺序控制;必须顶部声明层序、分层导入第三方样式、避免混用未分层规则,否则静默失效。

直接用 @layer 声明层级顺序,比堆选择器、滥用 !important 或靠加载顺序硬拼更可控——它让优先级变成可声明、可维护的结构,而不是玄学。
为什么嵌套和加类名还是压不过第三方样式?
因为 Sass 的 .modal { .header { } } 编译后只是 .modal .header,权重仍是 0,0,2,0;而 Bootstrap 或 Ant Design 可能用了 .ant-modal .ant-modal-header h2(0,0,2,1)或带 ID 的规则,天然更高。嵌套不等于隔离,也不提升 specificity。
- 检查开发者工具里被划掉的样式,悬停看 specificity 四元组值,别猜
- 第三方库样式常在 HTML 中最后
<link>,但权重高才是主因,不是“后加载就赢” -
@import是文本拼接,所有类名、变量都进全局作用域,根本没作用域这回事
用 @layer 显式控制层叠顺序
CSS 原生 @layer 让你提前划好“地盘”,不用赌加载顺序或拼权重。Sass 支持它,但得确保构建工具输出的是标准 CSS(比如 Vite 4.3+、Webpack 5.76+ 默认支持)。
- 按业务逻辑分层:
@layer base, components, overrides; - 第三方样式建议塞进
@layer vendor;,自己业务放@layer app; - 同一层内仍走原有层叠规则(specificity + 源码顺序),
@layer只管层间高低 - 最终 CSS 必须保留
@layer声明,否则降级为普通规则——检查构建产物,别只信源码
搭配 @use 隔离变量与 mixin,避免命名污染
@use 不解决类名冲突,但它让 $z-modal、@mixin button-reset() 真正私有,防止不同模块定义同名变量互相覆盖。
立即学习“前端免费学习笔记(深入)”;
- 必须写在文件顶部,不能放在
@if或规则块里 - 变量默认不可见,要用
base.$color-primary这种命名空间语法访问 - 旧项目混用
@import和@use会直接编译失败,得全量切换 - Bootstrap 5.3+ 才支持
@use,老版本只能继续@import,无法享受模块隔离
类名冲突必须靠前缀,不是靠嵌套
Sass 的 & 是语法糖,.uikit-modal { &__header { } } 编译出 .uikit-modal__header,这才是真正隔离的关键。没有唯一前缀,再深的嵌套也白搭。
- 根选择器必须带项目/组件级前缀,如
.uikit-modal,禁用.my-modal这类泛化名 -
&__body正确,& __body(中间空格)会生成全局__body类,直接失效 - 动态插入的 DOM(如 Modal 挂到
document.body)会逃出容器,必须显式传container: '.uikit-modal' - 如果用 Webpack/Vite,
Button.module.scss+ CSS Modules 是另一条路,但纯 HTML 场景下只能手动前缀
最易被忽略的是:CSS 层叠不是“谁写在后面谁赢”,而是 specificity + @layer 顺序 + 来源类型(内联 > ID > class)共同决定的。改样式前先打开 F12 看被划掉的规则和 specificity 值,比盲目加 !important 或再套一层 .wrapper .card .content .title 有用得多。


















