@mixin 和 @include

混合可以让您定义可以在整个样式表中重复使用的样式。它们使避免使用非语义类(如.float-left)以及在库中分发样式的集合变得容易。

混入正在使用的定义@mixin在规则,信息被写入@mixin <name> { ... }@mixin name(<arguments...>) { ... }。mixin的名称可以是任何Sass标识符,并且可以包含除顶级语句之外的任何语句。它们可用于封装可以放入单个样式规则中的样式 ; 它们可以包含自己的样式规则,这些规则可以嵌套在其他规则中或包含在样式表的顶层;或者它们只能用来修改变量。

混入是使用包括在当前上下文@include在规则,信息被写入@include <name>@include <name>(<arguments...>),与混入的被包括的名称。

SCSS  语法

@mixin reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin horizontal-list {
  @include reset-list;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: 2em;
    }
  }
}

nav ul {
  @include horizontal-list;
}

Sass语法

@mixin reset-list
  margin: 0
  padding: 0
  list-style: none


@mixin horizontal-list
  @include reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em




nav ul
  @include horizontal-list

CSS  输出

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}











???? 有趣的事实:

像所有Sass标识符一样,混入名称将连字符和下划线视为相同。这意味着reset-listreset_list都引用相同的mixin。这是Sass成立初期的历史保留,当时它允许标识符名称中使用下划线。Sass添加了对连字符的支持以匹配CSS的语法后,两者就变得等效了,从而使迁移更加容易。

参数永久链接参数

Mixins也可以接受参数,这样每次调用它们时都可以自定义其行为。@mixin在混入名称之后的规则中,将参数指定为变量名称列表,并用括号括起来。然后,必须以SassScript表达式的形式将mixin包含在相同数量的参数中。这些表达式的值可以在mixin的体内作为相应变量使用。

SCSS  语法

@mixin rtl($property, $ltr-value, $rtl-value) {
  #{$property}: $ltr-value;

  [dir=rtl] & {
    #{$property}: $rtl-value;
  }
}

.sidebar {
  @include rtl(float, left, right);
}

Sass语法

@mixin rtl($property, $ltr-value, $rtl-value)
  #{$property}: $ltr-value

  [dir=rtl] &
    #{$property}: $rtl-value



.sidebar
  @include rtl(float, left, right)

CSS  输出

.sidebar {
  float: left;
}
[dir=rtl] .sidebar {
  float: right;
}





???? 有趣的事实:

参数列表也可以有逗号结尾!这样可以在重构样式表时更轻松地避免语法错误。

可选参数永久链接可选参数

通常,当包含mixin时,必须传递mixin声明的每个参数。但是,您可以通过定义默认值来使参数成为可选参数,如果未传递该参数,则将使用该默认值。缺省值使用与变量声明相同的语法:变量名,后跟冒号和SassScript表达式。这使得定义灵活的混合API变得容易,这些API可以简单或复杂的方式使用。

SCSS  语法

@mixin replace-text($image, $x: 50%, $y: 50%) {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;

  background: {
    image: $image;
    repeat: no-repeat;
    position: $x $y;
  }
}

.mail-icon {
  @include replace-text(url("/images/mail.svg"), 0);
}

Sass语法

@mixin replace-text($image, $x: 50%, $y: 50%)
  text-indent: -99999em
  overflow: hidden
  text-align: left

  background:
    image: $image
    repeat: no-repeat
    position: $x $y

.mail-icon
  @include replace-text(url("/images/mail.svg"), 0)



CSS  输出

.mail-icon {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;
  background-image: url("/images/mail.svg");
  background-repeat: no-repeat;
  background-position: 0 50%;
}







???? 有趣的事实:

默认值可以是任何SassScript表达式,甚至可以引用更早的参数!

关键字参数永久链接关键字参数

当包含mixin时,除了按参数在列表中的位置传递参数外,还可以按名称传递参数。这对于具有多个可选参数的混合对象或布尔名称的含义特别有用,而布尔参数的含义在没有名称时不明显。关键字参数与变量声明可选参数使用相同的语法。

SCSS  语法

@mixin square($size, $radius: 0) {
  width: $size;
  height: $size;

  @if $radius != 0 {
    border-radius: $radius;
  }
}

.avatar {
  @include square(100px, $radius: 4px);
}

Sass语法

@mixin square($size, $radius: 0)
  width: $size
  height: $size

  @if $radius != 0
    border-radius: $radius



.avatar
  @include square(100px, $radius: 4px)

CSS  输出

.avatar {
  width: 100px;
  height: 100px;
  border-radius: 4px;
}







Head️抬头!

因为任何参数都可以按名称传递,所以在重命名mixin的参数时要小心……这可能会破坏您的用户!将旧名称作为可选参数保留一段时间并在任何人通过的情况下打印警告会很有帮助,因此他们知道要迁移到新参数。

接受任意论点永久链接接受任意论点

有时,mixin能够接受任意数量的参数很有用。如果@mixin声明中的最后一个参数以结尾...,则该mixin的所有其他参数将作为列表传递给该参数。此参数称为参数列表

SCSS  语法

@mixin order($height, $selectors...) {
  @for $i from 0 to length($selectors) {
    #{nth($selectors, $i + 1)} {
      position: absolute;
      height: $height;
      margin-top: $i * $height;
    }
  }
}

@include order(150px, "input.name", "input.address", "input.zip");






Sass语法

@mixin order($height, $selectors...)
  @for $i from 0 to length($selectors)
    #{nth($selectors, $i + 1)}
      position: absolute
      height: $height
      margin-top: $i * $height




@include order(150px, "input.name", "input.address", "input.zip")






CSS  输出

input.name {
  position: absolute;
  height: 150px;
  margin-top: 0px;
}

input.address {
  position: absolute;
  height: 150px;
  margin-top: 150px;
}

input.zip {
  position: absolute;
  height: 150px;
  margin-top: 300px;
}

接受任意关键字参数永久链接接受任意关键字参数

参数列表也可以用于接受任意关键字参数。该meta.keywords()函数接受一个参数列表,并返回传递给mixin的任何其他关键字,这些关键字作为从参数名称(不包括)到这些参数值的映射$

SCSS  语法

@use "sass:meta";

@mixin syntax-colors($args...) {
  @debug meta.keywords($args);
  // (string: #080, comment: #800, variable: $60b)

  @each $name, $color in meta.keywords($args) {
    pre span.stx-#{$name} {
      color: $color;
    }
  }
}

@include syntax-colors(
  $string: #080,
  $comment: #800,
  $variable: #60b,
)

Sass语法

@use "sass:meta"

@mixin syntax-colors($args...)
  @debug meta.keywords($args)
  // (string: #080, comment: #800, variable: $60b)

  @each $name, $color in meta.keywords($args)
    pre span.stx-#{$name}
      color: $color




@include syntax-colors($string: #080, $comment: #800, $variable: #60b)




CSS  输出

pre span.stx-string {
  color: #080;
}

pre span.stx-comment {
  color: #800;
}

pre span.stx-variable {
  color: #60b;
}







???? 有趣的事实:

如果您从未向meta.keywords()函数传递参数列表,则该参数列表将不允许使用额外的关键字参数。这可以帮助您的mixin调用者确保它们没有误拼写任何参数名称。

传递任意论点永久链接传递任意论点

就像参数列表允许mixin接受任意的位置或关键字参数一样,可以使用相同的语法位置和关键字参数传递给mixin。如果传递的列表后面是...包含的最后一个参数,则其元素将被视为其他位置参数。同样,后面跟随的映射...将被视为其他关键字参数。您甚至可以一次通过两个!

SCSS  语法

$form-selectors: "input.name", "input.address", "input.zip" !default;

@include order(150px, $form-selectors...);

Sass语法

$form-selectors: "input.name", "input.address", "input.zip" !default

@include order(150px, $form-selectors...)

???? 有趣的事实:

由于参数列表同时跟踪位置参数和关键字参数,因此您可以使用它同时将其传递给另一个mixin。这使得为​​mixin定义别名非常容易!

SCSS  语法

@mixin btn($args...) {
  @warn "The btn() mixin is deprecated. Include button() instead.";
  @include button($args...);
}

Sass语法

@mixin btn($args...)
  @warn "The btn() mixin is deprecated. Include button() instead."
  @include button($args...)

内容块永久链接内容块

除了采用参数外,mixin还可以采用整个样式块,称为内容块。mixin可以通过将@content规则包含在其主体中来声明它占用了内容块。像Sass中的任何其他块一样,使用大括号将内容块传递进来,并代替@content 规则将其插入。

SCSS  语法

@mixin hover {
  &:not([disabled]):hover {
    @content;
  }
}

.button {
  border: 1px solid black;
  @include hover {
    border-width: 2px;
  }
}

Sass语法

@mixin hover
  &:not([disabled]):hover
    @content



.button
  border: 1px solid black
  @include hover
    border-width: 2px


CSS  输出

.button {
  border: 1px solid black;
}
.button:not([disabled]):hover {
  border-width: 2px;
}






???? 有趣的事实:

一个mixin可以包含多个@content规则。如果是这样,将分别为每个内容块添加内容块  @content

Head️抬头!

内容块是按词法作用域划分的,这意味着它只能看到包含mixin的作用域中的局部变量。它看不到传递给它的mixin中定义的任何变量,即使它们是在调用内容块之前定义的。

将参数传递给内容块永久链接将参数传递给内容块

兼容性:
Dart·Sass(Dart Sass)
从  1.15.0开始
LibSass
rubySass

一个mixin可以将参数传递给它的内容块,就像通过编写将参数传递给另一个mixin一样@content(<arguments...>)。编写内容块的用户可以通过编写接受参数@include <name> using (<arguments...>)。内容块的参数列表的工作方式类似于mixin的参数列表,@content工作传递给它的参数就像将参数传递给mixin一样。

Head️抬头!

如果mixin将参数传递到其内容块,则该内容块必须声明它接受这些参数。这意味着仅按位置(而不是按名称)传递参数是一个好主意,并且意味着传递更多参数是一项重大突破。

如果您想灵活地传递给内容块什么信息,请考虑将包含可能需要的信息的地图传递给它!

SCSS  语法

@mixin media($types...) {
  @each $type in $types {
    @media #{$type} {
      @content($type);
    }
  }
}

@include media(screen, print) using ($type) {
  h1 {
    font-size: 40px;
    @if $type == print {
      font-family: Calluna;
    }
  }
}

Sass语法

@mixin media($types...)
  @each $type in $types
    @media #{$type}
      @content($type)




@include media(screen, print) using ($type)
  h1
    font-size: 40px
    @if $type == print
      font-family: Calluna



CSS  输出

@media screen {
  h1 {
    font-size: 40px;
  }
}
@media print {
  h1 {
    font-size: 40px;
    font-family: Calluna;
  }
}





缩进的Mixin语法永久链接缩进的Mixin语法

缩进语法对定义和使用的混入,除了标准的特殊语法@mixin@include。Mixins是使用字符定义的=,而使用则包含在内+。尽管此语法比较简单,但一眼就很难理解,建议用户避免使用它。

Sass语法

=reset-list
  margin: 0
  padding: 0
  list-style: none

=horizontal-list
  +reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em

nav ul
  +horizontal-list

CSS  输出

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}