Sass 控制指令 #

什么是控制指令? #

控制指令允许你在样式中使用条件判断和循环,实现更复杂的样式逻辑。Sass 提供了四种控制指令:

指令 用途
@if 条件判断
@for 数值循环
@each 列表/映射遍历
@while 条件循环

@if 条件判断 #

基本语法 #

scss
@if condition {
  // 条件为真时执行
}

单条件 #

scss
$theme: dark;

body {
  @if $theme == dark {
    background-color: #1a1a1a;
    color: #ffffff;
  }
}

@else if 和 @else #

scss
$size: large;

.button {
  @if $size == small {
    padding: 5px 10px;
    font-size: 12px;
  } @else if $size == medium {
    padding: 10px 20px;
    font-size: 14px;
  } @else if $size == large {
    padding: 15px 30px;
    font-size: 16px;
  } @else {
    padding: 10px 20px;
    font-size: 14px;
  }
}

在混合宏中使用 #

scss
@mixin theme($mode: light) {
  @if $mode == dark {
    background-color: #1a1a1a;
    color: #ffffff;
  } @else {
    background-color: #ffffff;
    color: #333333;
  }
}

body {
  @include theme(dark);
}

在函数中使用 #

scss
@function get-color($type, $variant: base) {
  $colors: (
    primary: (
      base: #3498db,
      light: #5dade2,
      dark: #2980b9
    ),
    secondary: (
      base: #2ecc71,
      light: #58d68d,
      dark: #27ae60
    )
  );
  
  $color-map: map-get($colors, $type);
  
  @if $variant == light {
    @return map-get($color-map, light);
  } @else if $variant == dark {
    @return map-get($color-map, dark);
  } @else {
    @return map-get($color-map, base);
  }
}

.button {
  background-color: get-color(primary);
  border-color: get-color(primary, dark);
}

@for 循环 #

语法格式 #

scss
// 从 start 到 end(包含 end)
@for $var from start through end { }

// 从 start 到 end(不包含 end)
@for $var from start to end { }

through vs to #

scss
// through:包含结束值
@for $i from 1 through 3 {
  .item-#{$i} {
    width: $i * 100px;
  }
}
// 生成 .item-1, .item-2, .item-3

// to:不包含结束值
@for $i from 1 to 3 {
  .item-#{$i} {
    width: $i * 100px;
  }
}
// 生成 .item-1, .item-2

生成网格系统 #

scss
$columns: 12;

@for $i from 1 through $columns {
  .col-#{$i} {
    width: percentage($i / $columns);
  }
}

// 编译后
.col-1 { width: 8.333%; }
.col-2 { width: 16.667%; }
.col-3 { width: 25%; }
// ... 直到 .col-12

生成间距类 #

scss
@for $i from 0 through 5 {
  .mt-#{$i} { margin-top: $i * 8px; }
  .mb-#{$i} { margin-bottom: $i * 8px; }
  .ml-#{$i} { margin-left: $i * 8px; }
  .mr-#{$i} { margin-right: $i * 8px; }
  .p-#{$i} { padding: $i * 8px; }
}

// 编译后
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 8px; }
.mt-2 { margin-top: 16px; }
// ...

生成字体大小 #

scss
@for $i from 1 through 6 {
  .text-#{$i} {
    font-size: 2rem - ($i - 1) * 0.25rem;
  }
}

// 编译后
.text-1 { font-size: 2rem; }
.text-2 { font-size: 1.75rem; }
.text-3 { font-size: 1.5rem; }
.text-4 { font-size: 1.25rem; }
.text-5 { font-size: 1rem; }
.text-6 { font-size: 0.75rem; }

生成延迟动画 #

scss
@for $i from 1 through 5 {
  .delay-#{$i} {
    animation-delay: $i * 0.1s;
  }
}

// 编译后
.delay-1 { animation-delay: 0.1s; }
.delay-2 { animation-delay: 0.2s; }
.delay-3 { animation-delay: 0.3s; }
.delay-4 { animation-delay: 0.4s; }
.delay-5 { animation-delay: 0.5s; }

@each 遍历 #

遍历列表 #

scss
$colors: red, green, blue;

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

// 编译后
.text-red { color: red; }
.bg-red { background-color: red; }
.text-green { color: green; }
.bg-green { background-color: green; }
.text-blue { color: blue; }
.bg-blue { background-color: blue; }

遍历映射 #

scss
$colors: (
  primary: #3498db,
  secondary: #2ecc71,
  danger: #e74c3c,
  warning: #f39c12
);

@each $name, $color in $colors {
  .btn-#{$name} {
    background-color: $color;
    
    &:hover {
      background-color: darken($color, 10%);
    }
  }
}

// 编译后
.btn-primary {
  background-color: #3498db;
}
.btn-primary:hover {
  background-color: #2980b9;
}
// ...

遍历嵌套列表 #

scss
$sizes: (
  (small, 10px, 12px),
  (medium, 15px, 14px),
  (large, 20px, 16px)
);

@each $name, $padding, $font-size in $sizes {
  .btn-#{$name} {
    padding: $padding;
    font-size: $font-size;
  }
}

// 编译后
.btn-small { padding: 10px; font-size: 12px; }
.btn-medium { padding: 15px; font-size: 14px; }
.btn-large { padding: 20px; font-size: 16px; }

生成图标类 #

scss
$icons: (
  home: "\e800",
  user: "\e801",
  settings: "\e802",
  search: "\e803"
);

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

// 编译后
.icon-home::before { content: "\e800"; font-family: "iconfont"; }
.icon-user::before { content: "\e801"; font-family: "iconfont"; }
.icon-settings::before { content: "\e802"; font-family: "iconfont"; }
.icon-search::before { content: "\e803"; font-family: "iconfont"; }

生成断点样式 #

scss
$breakpoints: (
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
);

@each $name, $value in $breakpoints {
  @media (min-width: $value) {
    .hidden-#{$name} {
      display: none !important;
    }
  }
}

// 编译后
@media (min-width: 576px) {
  .hidden-sm { display: none !important; }
}
@media (min-width: 768px) {
  .hidden-md { display: none !important; }
}
// ...

@while 循环 #

基本语法 #

scss
@while condition {
  // 循环体
}

基本示例 #

scss
$i: 1;

@while $i <= 5 {
  .item-#{$i} {
    width: $i * 20px;
  }
  $i: $i + 1;
}

// 编译后
.item-1 { width: 20px; }
.item-2 { width: 40px; }
.item-3 { width: 60px; }
.item-4 { width: 80px; }
.item-5 { width: 100px; }

生成字体大小 #

scss
$font-size: 2rem;
$i: 1;

@while $font-size >= 0.75rem {
  .text-#{$i} {
    font-size: $font-size;
  }
  $font-size: $font-size - 0.25rem;
  $i: $i + 1;
}

// 编译后
.text-1 { font-size: 2rem; }
.text-2 { font-size: 1.75rem; }
.text-3 { font-size: 1.5rem; }
.text-4 { font-size: 1.25rem; }
.text-5 { font-size: 1rem; }
.text-6 { font-size: 0.75rem; }

注意事项 #

scss
// 警告:确保循环能够终止
$i: 1;
@while $i <= 10 {
  // 必须更新条件变量
  $i: $i + 1;
}

// 错误:无限循环
$i: 1;
@while $i <= 10 {
  // 忘记更新 $i,会导致无限循环
}

组合使用 #

@if + @for #

scss
@for $i from 1 through 12 {
  .col-#{$i} {
    width: percentage($i / 12);
    
    @if $i <= 6 {
      float: left;
    } @else {
      float: right;
    }
  }
}

@each + @if #

scss
$colors: (
  primary: #3498db,
  secondary: #2ecc71,
  danger: #e74c3c
);

@each $name, $color in $colors {
  .btn-#{$name} {
    background-color: $color;
    
    @if $name == danger {
      border: 2px solid darken($color, 20%);
    }
  }
}

嵌套循环 #

scss
$sizes: (sm, md, lg);
$directions: (t, b, l, r);

@each $size in $sizes {
  @each $dir in $directions {
    .m#{$dir}-#{$size} {
      margin-#{$dir}: 10px;
    }
  }
}

// 编译后
.mt-sm { margin-top: 10px; }
.mb-sm { margin-bottom: 10px; }
.ml-sm { margin-left: 10px; }
.mr-sm { margin-right: 10px; }
// ...

实际应用示例 #

完整网格系统 #

scss
$columns: 12;
$breakpoints: (
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
);

// 基础列
@for $i from 1 through $columns {
  .col-#{$i} {
    flex: 0 0 percentage($i / $columns);
    max-width: percentage($i / $columns);
  }
}

// 响应式列
@each $bp, $value in $breakpoints {
  @media (min-width: $value) {
    @for $i from 1 through $columns {
      .col-#{$bp}-#{$i} {
        flex: 0 0 percentage($i / $columns);
        max-width: percentage($i / $columns);
      }
    }
  }
}

完整间距系统 #

scss
$spacer: 1rem;
$spacers: (
  0: 0,
  1: $spacer * 0.25,
  2: $spacer * 0.5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3
);

$properties: (
  m: margin,
  p: padding
);

$directions: (
  t: top,
  b: bottom,
  l: left,
  r: right,
  x: (left, right),
  y: (top, bottom)
);

@each $prop-key, $prop-value in $properties {
  @each $spacer-key, $spacer-value in $spacers {
    // 全方向
    .#{$prop-key}-#{$spacer-key} {
      #{$prop-value}: $spacer-value;
    }
    
    // 单方向
    @each $dir-key, $dir-value in $directions {
      @if type-of($dir-value) == list {
        .#{$prop-key}#{$dir-key}-#{$spacer-key} {
          @each $dir in $dir-value {
            #{$prop-value}-#{$dir}: $spacer-value;
          }
        }
      } @else {
        .#{$prop-key}#{$dir-key}-#{$spacer-key} {
          #{$prop-value}-#{$dir-value}: $spacer-value;
        }
      }
    }
  }
}

主题系统 #

scss
$themes: (
  light: (
    bg: #ffffff,
    text: #333333,
    primary: #3498db
  ),
  dark: (
    bg: #1a1a1a,
    text: #ffffff,
    primary: #5dade2
  )
);

@mixin theme($theme-name) {
  $theme: map-get($themes, $theme-name);
  
  background-color: map-get($theme, bg);
  color: map-get($theme, text);
  
  .button {
    background-color: map-get($theme, primary);
  }
}

// 生成主题类
@each $name, $colors in $themes {
  .theme-#{$name} {
    @include theme($name);
  }
}

最佳实践 #

1. 避免过度使用 #

scss
// 好:适度使用
@for $i from 1 through 5 {
  .mt-#{$i} { margin-top: $i * 8px; }
}

// 不好:过度生成
@for $i from 1 through 100 {
  .mt-#{$i} { margin-top: $i * 1px; }
}

2. 使用有意义的变量名 #

scss
// 好
@for $column from 1 through $total-columns {
  .col-#{$column} { width: percentage($column / $total-columns); }
}

// 不好
@for $i from 1 through $n {
  .col-#{$i} { width: percentage($i / $n); }
}

3. 结合映射使用 #

scss
// 好:使用映射配置
$colors: (primary: #3498db, secondary: #2ecc71);
@each $name, $color in $colors {
  .text-#{$name} { color: $color; }
}

// 不好:硬编码
.text-primary { color: #3498db; }
.text-secondary { color: #2ecc71; }

下一步 #

掌握了控制指令后,继续学习 运算符,深入了解 Sass 的计算能力!

最后更新:2026-03-28