Sass 控制命令:@if,@for,@each 和@while

Sass 的控制命令可以让你在 @mixin@function 中实现条件判断和循环逻辑,是编写可复用、可配置的 Sass 库的基础。掌握这些指令,才能真正写出灵活健壮的 SCSS 代码。

@if / @else if / @else

@if 指令根据条件返回对应的样式块。配合 @else if@else 可以实现多分支判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$theme: dark;

.header {
@if $theme == dark {
background: #333;
color: #fff;
} @else if $theme == light {
background: #fff;
color: #333;
} @else {
background: #f0f0f0;
color: #666;
}
}

编译结果:

1
2
3
4
.header {
background: #333;
color: #fff;
}

与 @debug / @warn / @error 配合

在分支中埋入调试或错误提示信息,可以帮助定位问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$z-index-map: (
modal: 1000,
dropdown: 100,
default: 1
);

@function z-index($key) {
@if map-has-key($z-index-map, $key) {
@return map-get($z-index-map, $key);
} @else {
@error "未知的层级层级: #{$key},可选值有: #{map-keys($z-index-map)}";
}
}

.modal { z-index: z-index(modal); } // ✅ 正常编译
.foo { z-index: z-index(toast); } // ❌ 编译报错:Error: 未知的层级层级: toast,...
  • @debug:在终端输出调试信息,不中断编译
  • @warn:输出警告信息,不中断编译
  • @error:输出错误信息并中断编译(适合校验参数合法性)

@for

@for 有两种形式:

  • through:包含结束值
  • to:不包含结束值
1
2
3
4
5
6
7
8
9
// through:包含 4
@for $i from 1 through 4 {
.col-#{$i} { width: 25% * $i; }
}

// to:不包含 4
@for $i from 1 to 4 {
.col-#{$i} { width: 100% / 3 * $i; }
}

编译结果:

1
2
3
4
5
6
7
8
9
10
/* through */
.col-1 { width: 25%; }
.col-2 { width: 50%; }
.col-3 { width: 75%; }
.col-4 { width: 100%; }

/* to */
.col-1 { width: 33.3333333333%; }
.col-2 { width: 66.6666666667%; }
.col-3 { width: 100%; }

递减循环

@for 也支持从大到小循环:

1
2
3
@for $i from 5 through 1 {
.fs-#{$i} { font-size: 12px + $i * 2px; }
}

结合 length() 遍历列表

1
2
3
4
5
6
7
$breakpoints: 576px, 768px, 992px, 1200px;

@for $i from 1 through length($breakpoints) {
@media (min-width: nth($breakpoints, $i)) {
.container-#{$i} { max-width: nth($breakpoints, $i); }
}
}

@each

遍历列表

1
2
3
4
5
6
7
$sizes: small medium large;

@each $size in $sizes {
.btn-#{$size} {
font-size: if($size == small, 12px, if($size == medium, 14px, 16px));
}
}

遍历 Map(多变量赋值)

@each 支持同时遍历 key 和 value:

1
2
3
4
5
6
7
8
9
10
11
$colors: (
primary: #409eff,
success: #67c23a,
warning: #e6a23c,
danger: #f56c6c,
);

@each $name, $color in $colors {
.text-#{$name} { color: $color; }
.bg-#{$name} { background: $color; }
}

编译结果:

1
2
3
4
5
6
7
8
.text-primary { color: #409eff; }
.bg-primary { background: #409eff; }
.text-success { color: #67c23a; }
.bg-success { background: #67c23a; }
.text-warning { color: #e6a23c; }
.bg-warning { background: #e6a23c; }
.text-danger { color: #f56c6c; }
.bg-danger { background: #f56c6c; }

遍历多重列表

1
2
3
4
5
6
7
8
9
10
11
$icons: (
("edit", "\f044"),
("save", "\f0c7"),
("trash", "\f1f8"),
);

@each $name, $code in $icons {
.icon-#{$name}::before {
content: $code;
}
}

实用示例:生成工具类

1
2
3
4
5
6
7
8
9
$spacing: (0, 4px, 8px, 12px, 16px, 24px);
$sides: (t: top, b: bottom, l: left, r: right);

@each $prefix, $side in $sides {
@each $val in $spacing {
.m#{prefix}-#{$val} { margin-#{$side}: $val; }
.p#{prefix}-#{$val} { padding-#{$side}: $val; }
}
}

@while

@while 在条件为 true 时持续循环,适合无法预先确定迭代次数的场景。务必确保循环条件最终会变为 false,否则会造成死循环。

1
2
3
4
5
6
7
8
$i: 6;

@while $i > 0 {
.grid-span-#{$i} {
width: 100% / 6 * $i;
}
$i: $i - 1;
}

编译结果:

1
2
3
4
5
6
.grid-span-6 { width: 100%; }
.grid-span-5 { width: 83.3333333333%; }
.grid-span-4 { width: 66.6666666667%; }
.grid-span-3 { width: 50%; }
.grid-span-2 { width: 33.3333333333%; }
.grid-span-1 { width: 16.6666666667%; }

指令选择建议

场景推荐指令原因
条件分支@if / @else if / @else最直观的条件判断
已知迭代次数@for简洁、安全,不会死循环
遍历列表/Map@each语义清晰,支持多变量解构
未知迭代次数,依赖运行时条件@while最灵活,但需手动控制终止条件