SCSS 的 @each 无法自动递归遍历嵌套 Map,必须手动分层 @each + @if 守卫处理;Map 的 key 必须用引号字符串(如 "bg"),值需带单位,嵌套超两层应拆分为独立 Map。

为什么不能只用一层 @each 遍历嵌套 Map
SCSS 的 @each 只能解构一层键值对,遇到 value 是 map 的情况(比如 "primary": ("bg": #007bff, "text": #fff)),它不会自动递归。你写的 background-color: map-get($props, "bg") 能出结果,但 border-color、hover-bg 等其他键全被跳过——编译不报错,CSS 却缺样式。
必须手动分层:@each $name, $props in $button-variants 做外层遍历,内部再套一层 @each $prop-key, $prop-val in $props,并加守卫:
-
@if $prop-key == "hover-bg"才生成&:hover { background-color: $prop-val; } -
@if map-has-key($props, "border")再取值,否则map-get($props, "border")返回null,属性直接消失 - 嵌套超过两层(如
"primary": ("hover": ("disabled": ...)))建议拆成独立 map,别硬塞
Map 的 key 必须是带引号字符串,否则编译直接失败
写成 bg: #007bff 或 $key: "bg"; #{$key}: #007bff 全部非法。Sass 会把无引号的 bg 当变量名去查,结果报 Undefined variable "bg";动态拼接 key(#{$key})在 map 定义时也不被允许。
✅ 正确写法只有:"bg": #007bff、"hover-bg": darken(#007bff, 10%);大小写敏感,“BG” 和 “bg” 是两个 key。
立即学习“前端免费学习笔记(深入)”;
- 数字 key 可不加引号(
1: 0.25rem合法),但为统一维护,推荐全用字符串:"1": 0.25rem - 值必须带单位:
0.5rem✅,0.5❌(无单位数值参与运算会触发Invalid null operation) - 别把 margin 和 padding 塞进同一个 map——用途不同,后期改一个容易误伤另一个
生成响应式类时,@each + @for 组合比全量 @each 更可控
想生成 .col-sm-4、.col-md-6 这类栅格类,@for $i from 1 through $grid-columns 处理列数,@each $breakpoint, $width in $grid-breakpoints 控制断点,二者嵌套最稳。
错误做法:把断点写成数组 (sm, md, lg),再用 @each $bp in $breakpoints,结果没绑定宽度值,.col-sm-6 里连 flex-basis 都没有。
- 务必用
#{$grid-columns}参与 calc 字符串拼接:calc(100% / #{$grid-columns} * #{$i}),否则 SCSS 提前算成小数,旧版 Safari 渲染异常 - 避免每轮
@each都包一层@media,否则 CSS 体积线性爆炸(4 断点 × 12 列 × 2 属性 = 至少 96 行) - IE11 兼容需 fallback:
width+box-sizing: border-box,不能只靠flex-basis: calc(...)
方向类(如 mt-2、px-3)必须分层定义 Map 并嵌套 @each
靠一个 map 搞定所有组合不现实。正确结构是三个分离的 map:$spacing-types: ("m": "margin", "p": "padding")、$spacing-directions: ("t": "top", "x": ("left", "right"))、$spacers: ("2": 0.5rem),再三层 @each 嵌套。
关键判断逻辑在 direction 层:@if $dir-prop == "left right" 就同时设 left/right;@elseif $dir-prop == "top bottom" 就设 top/bottom;否则走单边。
- 别在循环里写
&:hover外置——伪类必须在@each $type, $props in $map内部,否则所有按钮 hover 都套同一套逻辑 - 响应式前缀(如
md:m-2)不是原生语法,得手动展开:@each $bp, $query in $breakpoints { @media #{$query} { .#{$bp}:m-#{$i} { margin: ($i * 0.25rem); } } } - 插值顺序影响可维护性:类名拼接逻辑(如
mt-#{$size})建议收口到函数里,避免分散在多处,换分隔符时不用全局搜
实际项目里最容易被忽略的是 map key 的引号规则和嵌套层级的显式展开——它们不报错,但会让生成结果静默失效。写完先检查编译输出 CSS 是否真有对应类,别只信 SCSS 语法通过。


















