sass 中 @mixin 重名冲突必须用 @use 模块系统解决,它通过命名空间隔离作用域、强制显式调用(如 f.container())并废弃 @import;%placeholder 更适合原子样式复用,避免冗余和冲突。

直接结论:Sass 中 @mixin 重名冲突无法靠“约定”规避,必须用 @use 模块系统强制隔离作用域——它让每个 mixin 只在被显式调用时才进入当前命名空间,且天然带前缀,彻底切断隐式覆盖链。
为什么 @import 是 mixin 冲突的根源
旧写法 @import "mixins/flex" 会把所有 @mixin flex-center、@mixin flex-between 全局注入,一旦另一个 @import "components/button" 也定义了同名 @mixin flex-center,后加载者直接覆盖前者,编译不报错,但样式已静默失效。
更隐蔽的问题是:你根本不知道哪个文件在哪儿悄悄重写了它。Dart Sass 3.0 已正式废弃 @import,报错信息里那句 DEPRECATION WARNING [import]: Sass @import rules are deprecated 不是提醒,是倒计时。
- 所有
@import必须替换成@use,哪怕只是单个文件 -
@use后的成员默认不可见,必须用namespace.mixin-name()调用,比如flex.flex-center() - 同一个文件多次
@use不会重复执行,也不会合并变量或 mixin,安全
如何用 @use + as 控制 mixin 命名空间
假设你有两个模块:_flex.scss 和 _layout.scss,都定义了 @mixin container。不加处理直接 @use 会因重名报错:"container" is defined multiple times。
正确做法是显式重命名其中一方:
@use "flex" as f;
@use "layout" as l;
.example {
@include f.container();
@include l.container();
}
这样既避免冲突,又保留语义——f.container() 表示“flex 容器”,l.container() 表示“layout 容器”,谁调用谁负责厘清上下文。
- 不要用
@use "flex" as *,它等价于旧@import,取消命名空间,回到冲突起点 - 团队内可约定前缀规则,比如统一用
u-(utility)、c-(component),但不如@use的命名空间可靠 - 第三方库如
sass:math也必须@use "sass:math",否则可能和项目内$pi变量撞名
当必须复用基础 mixin 时,优先选 %placeholder 而非 @mixin
比如重置 margin/padding、隐藏文本、清除浮动这类原子级样式,用 @mixin reset-all 多次调用会导致 CSS 体积膨胀,且若两个模块都定义了同名 reset-all,@use 也无法解决——因为它们本就不该被“调用”,而应被“继承”。
%reset 占位符才是正解:
// _base.scss
%reset {
margin: 0;
padding: 0;
}
// _card.scss
@use "base";
.card {
@extend base.%reset; // 显式指定来源,无歧义
}
-
%placeholder不生成独立 CSS,只在@extend处按需注入,零冗余 - 它不参与命名空间导出,不会出现在
@use的可访问列表中,天然避开了 mixin 重名问题 - 注意:
%不支持插值,%u-mt-#{$n}会报错,这种动态场景仍需@mixin+@use配合
迁移时最容易漏掉的三个点
从 @import 切到 @use 不是全局替换字符串那么简单,以下三点常被跳过,导致编译失败或行为异常:
-
@use必须放在文件最顶部,且不能在嵌套规则(如.block { ... })内部;而@import曾被滥用在任意位置 - 原
@import中带条件逻辑的写法(如@if $theme == 'dark' { @import "dark"; })无法直接转为@use,需改用函数或配置变量驱动 - 如果旧项目用了
!global强行覆盖变量(如$primary-color: red !global),@use下该写法失效——变量变成模块私有,必须通过@use "vars" with ($primary-color: red)显式传入
真正麻烦的从来不是语法转换,而是那些藏在 @import 底层的隐式依赖和全局污染——它们不会报错,但会让 @use 的隔离效果打折扣。动手前先 grep 一遍项目里的 !global 和裸 @import,比写一百行新 mixin 都重要。










