流控制规则 Flow Control Rules

Sass 提供了许多规则,可以控制样式是否被发出,或者多次发出它们,变化很小。

它们也可以用于 mixinsfunctions 来编写小算法,使编写 Sass 更容易。 Sass 支持四种流量控制规则:

  • @if 控制是否评估块。
  • @eachlist 中的每个元素或 map 中的每一对计算块 (/值/地图)。
  • @for 评估一个块一定次数。
  • @while 评估一个块,直到满足特定条件。

@if和@else

@if 规则写成 @if <expression> { ... },它控制是否对其块进行评估(包括将任何样式作为 CSS 发出)。 expression 通常返回 truefalse——如果表达式返回 true,则块是 已评估,如果表达式返回“false”,则不是。

scss
Scss
scss
@mixin avatar($size, $circle: false) {
  width: $size;
  height: $size;

  @if $circle {
    border-radius: $size / 2;
  }
}

.square-av {
  @include avatar(100px, $circle: false);
}
.circle-av {
  @include avatar(100px, $circle: true);
}

@else

一个 @if 规则后面可以跟着一个 @else 规则,写成 @else { ... }。 如果“@if”表达式返回“false”,则评估此规则的块。

scss
Scss
scss
$light-background: #f2ece4;
$light-text: #036;
$dark-background: #6b717f;
$dark-text: #d2e1dd;

@mixin theme-colors($light-theme: true) {
  @if $light-theme {
    background-color: $light-background;
    color: $light-text;
  } @else {
    background-color: $dark-background;
    color: $dark-text;
  }
}

.banner {
  @include theme-colors($light-theme: true);
  body.dark & {
    @include theme-colors($light-theme: false);
  }
}

条件表达式可能包含 boolean operators (and, or, not).

@else if

您还可以通过编写@else if <expression> { ... }来选择是否评估@else规则的块。 如果这样做,只有当前面的@if表达式返回false 并且 @else if表达式返回true时,才会评估该块。

事实上,您可以在 @if 之后链接任意多个 @else if。 链中表达式返回 true 的第一个块将被计算,其他的则不计算。 如果在链的末尾有一个普通的@else,如果其他所有块都失败,则会评估它的块。

scss
Scss
scss
@use "sass:math";

@mixin triangle($size, $color, $direction) {
  height: 0;
  width: 0;

  border-color: transparent;
  border-style: solid;
  border-width: math.div($size, 2);

  @if $direction == up {
    border-bottom-color: $color;
  } @else if $direction == right {
    border-left-color: $color;
  } @else if $direction == down {
    border-top-color: $color;
  } @else if $direction == left {
    border-right-color: $color;
  } @else {
    @error "Unknown direction #{$direction}.";
  }
}

.next {
  @include triangle(5px, black, right);
}

布尔值

在允许使用 true 或 false 的任何地方,您也可以使用其他值。 值 falsenullfalsey,这意味着 Sass 认为它们表示虚假并导致条件失败。 每个其他值都被认为是_truthy_,因此 Sass 认为它们像“true”一样工作并导致条件成功。

例如,如果你想检查一个字符串是否包含空格,你可以只写 string.index($string, " ")。 如果未找到字符串,string.index() 函数 返回 null,否则返回一个数字。

⚠️ 注意!

有些语言认为更多的值是错误的,而不仅仅是falsenull。 Sass 不是那些语言之一! 空字符串、空列表和数字“0”在 Sass 中都是真值。

@each

@each 规则使得为 list 中的每个元素或 map 中的每个元素生成样式或评估代码变得容易. 它非常适合重复样式,它们之间只有一些变化。 它通常写成@each <variable> in <expression> { ... },其中 expression 返回一个列表。 依次为列表中的每个元素评估块,并将其分配给给定的变量名称。

scss
Scss
scss
$sizes: 40px, 50px, 80px;

@each $size in $sizes {
  .icon-#{$size} {
    font-size: $size;
    height: $size;
    width: $size;
  }
}

使用映射

您还可以使用“@each”来遍历映射中的每个键/值对,方法是将其写入@each <variable>, <variable> in <expression> { ... }。 键被分配给第一个变量名,元素被分配给第二个。

scss
Scss
scss
$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");

@each $name, $glyph in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
  }
}

解构

如果您有一个列表列表,您可以使用“@each”自动将变量分配给内部列表中的每个值,方法是将其写入@each <variable...> in <expression> { ... } . 这被称为_destructuring_,因为变量匹配内部列表的结构。 每个变量名称都分配给列表中相应位置的值,如果列表没有足够的值,则分配给 null

scss
Scss
scss
$icons:
  "eye" "\f112" 12px,
  "start" "\f12e" 16px,
  "stop" "\f12f" 10px;

@each $name, $glyph, $size in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
    font-size: $size;
  }
}

💡 有趣的事实:

因为 @each 支持解构和 maps count as lists of lists@each 的地图支持不需要特别支持地图就可以工作。

@for

@for 规则,写成@for <variable> from <expression> to <expression> { ... }@for <variable> from <expression> through <expression> { ... }, 从一个数字(第一个 expression 的结果)向上或向下计数到另一个(第二个的结果),并为中间的每个数字计算一个块。 沿途的每个数字都分配给给定的变量名称。 如果使用to,则排除最后的数字; 如果使用 through,则包含在内。

scss
Scss
scss
$base-color: #036;

@for $i from 1 through 3 {
  ul:nth-child(3n + #{$i}) {
    background-color: lighten($base-color, $i * 5%);
  }
}

@while

@while 规则,写为 @while <expression> { ... },如果其 expression 返回 true,则评估其块。 然后,如果它的表达式仍然返回“true”,它会再次评估它的块。 这一直持续到表达式最终返回“false”。

scss
Scss
scss
@use "sass:math";

/// Divides `$value` by `$ratio` until it's below `$base`.
@function scale-below($value, $base, $ratio: 1.618) {
  @while $value > $base {
    $value: math.div($value, $ratio);
  }
  @return $value;
}

$normal-font-size: 16px;
sup {
  font-size: scale-below(20px, 16px);
}

⚠️ 注意!

虽然 @while 对于一些特别复杂的样式表是必需的,但您通常最好使用 @each@for 如果它们中的任何一个都可以工作。 它们对读者来说更清晰,编译起来通常也更快。

真实与虚假

在允许使用 true 或 false 的任何地方,您也可以使用其他值。 值 falsenull 是_falsey_,这意味着 Sass 认为它们表示虚假并导致条件失败。 每个其他值都被认为是_truthy_,因此 Sass 认为它们像“true”一样工作并导致条件成功。

例如,如果你想检查一个字符串是否包含空格,你可以只写 string.index($string, " ")。 如果未找到字符串,string.index() 函数 返回 null,否则返回一个数字。

⚠️ 注意!

有些语言认为更多的值是错误的,而不仅仅是“false”和“null”。 Sass 不是那些语言之一! 空字符串、空列表和数字“0”在 Sass 中都是真值。