@each是生成语义化类名的唯一合理选择,因其能直接绑定键名(如"primary")与样式值,确保类名可读、可维护;而@for仅产出无意义数字索引,增删项即导致映射错乱。

直接用 @each 遍历 map,别碰 @for 生成语义化类名——后者只能出 .text-1 这种无意义编号,一改颜色顺序就全错。
为什么 @each 是颜色/间距/图标类的唯一合理选择
颜色、断点、图标这些数据天然带键名("success"、"sm"、"home"),而类名必须靠键名保证可读性和维护性。用 @for 只能得到索引数字,map-get($colors, $i) 还得手动查表,既慢又易错。
-
$colors: ("primary": #0d6efd, "success": #198754);→@each $name, $color in $colors { .text-#{$name} { color: $color; } }安全产出.text-primary - 若误写成
@for $i from 1 through length($colors),$i是 1 或 2,跟"primary"没绑定关系;增删一个颜色,.text-2就从success变成warning -
@each要求变量是 map 或 list;传字符串"primary success"会直接报错Invalid CSS after "",不是语法问题,是类型不匹配
@for 只适合纯数字序列类名,且边界必须用 through
生成 .m-1 到 .m-12、.col-1 到 .col-24 这类编号明确、无语义的工具类时,@for 最直白。但 to 是开区间,@for $i from 1 to 12 只到 11,漏掉关键的 .m-12。
- 必须写
@for $i from 1 through 12,闭区间才保底不漏 -
percentage($i / 12)会因整数除法得 0%,要写成percentage($i / 12.0)或提前定义$unit: 100% / 12再算calc(#{$unit} * #{$i}) - 单位混用危险:
#{$i}px和$i * 0.25rem并存,Sass 可能静默拼接字符串,浏览器解析失败却无报错
嵌套 @each 才能安全生成方向+数值组合类
单层循环搞不定 .mt-2、.pr-4 这种结构。必须外层遍历方向映射,内层遍历间距值,且属性名要拼对——margin-#{$full} 不是 margin#{$dir}。
立即学习“前端免费学习笔记(深入)”;
- 方向 map 要定义清楚:
$dirs: (t: "top", r: "right", b: "bottom", l: "left"); - 内层必须用 map(非 list)存间距:
$spacers: ("1": 0.25rem, "2": 0.5rem);,否则插值.m#{$dir}-#{$s}中的$s是数字还是字符串不可控 - 避免在循环里重复调
map-get();要用@each $bp, $query in $breakpoints,别写@each $bp in map-keys($breakpoints) { @media #{map-get($breakpoints, $bp)} { ... } }
插值语法踩坑:选择器开头不能是 #{$var}
.#{$name} 直接编译失败,不是变量没定义,是 Sass 解析器在语法分析阶段就拒绝——选择器开头必须是字母、下划线或 &,而插值此时未展开,被视为空起始。
- 正确路径只有两个:
@each循环中写.btn-#{$type}(前缀固定),或嵌套规则里用&-#{$suffix}+@at-root提升作用域 - 后缀含破折号(如
"max-sm")或数字开头(如"2xl"),必须用quote("max-sm")包裹,否则 Sass 把-当减法、把2xl当非法标识符 - 别在
@extend中插值类名,@extend .#{$name}不合法,会崩
真正麻烦的从来不是写循环,而是 map 数据本身是否干净:键名重复会让 map-get 返回错位值,非字符串键在旧版 Sass 中顺序不保证,rgba() 值直接喂给 lighten() 会静默失效——这些细节比语法更常导致上线后样式错乱。


















