类名冲突本质是命名空间未隔离,而非@for本身问题;多个循环共用同一键名且无类型前缀(如.mt-1与.m-1并存),或分散文件重复执行相同@for,导致全局类名重复输出。
不是 @for 本身导致重复,而是多个循环共用同一组键名(比如都遍历 $spacers)且未区分类型前缀。例如:一个循环生成 .mt-#{$i},另一个直接写 .m-#{$i},但两者都用了 1 through 4,结果 .m-1 和 .mt-1 在 CSS 中并存——看似不同,实际在某些压缩工具或调试器里可能因排序/折叠被误认为“重复声明”。更隐蔽的问题是:如果两个文件各自 @use "spacing" 并调用相同逻辑,又没加模块前缀,最终输出的类名完全一样,毫无隔离。
常见错误写法:
@for $i from 1 through 4 {.mt-#{$i} { margin-top: $i * 0.25rem; }.mb-#{$i} { margin-bottom: $i * 0.25rem; }}这段代码没问题;但一旦你把它放进某个组件文件里,又在另一个组件里复制粘贴一份相同的 @for 块,Sass 不会合并、也不会报重名——它就老老实实输出两套 .mt-1 到 .mt-4。浏览器解析时,后出现的规则会覆盖前一个(如果权重相同),而开发者根本看不到警告。_utilities.scss),禁止分散定义@forward 控制暴露,而非每个文件都跑一遍 @for
/^m[tblrxy]-d+$/)当 $breakpoints 定义为 ("md": 768px, "lg": 1024px),且你在 @each $breakpoint, $width in $breakpoints 中直接拼接 .#{$breakpoint}-mt-#{$i},Sass 会把字符串键("md")原样带引号输出,结果是 "."md"-mt-1" —— 浏览器无法匹配这个选择器,DevTools 里可能显示为空白或报错 Invalid selector,而你却以为是类名“重复失效”。
$breakpoints 的 key 是无引号标识符(md: 768px),不是字符串("md": 768px)str-replace 或 meta.inspect() 清洗,或换用 map-keys() + nth() 手动取值md-mt,看是否真出现带反斜杠和引号的类名比如你在 JS 中拼出 class="mt-${size}",但 $size 是运行时变量,PurgeCSS 默认不认识这种模式,会删掉所有 .mt-*;结果页面上看起来“类没生效”,你以为是命名冲突,其实是类根本没进最终 CSS。同样,如果组件库和你自己的工具类都定义了 .sr-only,且都没加前缀,那才是真冲突——但根源不在 @for,而在缺乏统一前缀约定和模块隔离。