@mixin 和 @include

Mixins 允许你定义可以在整个样式表中重复使用的样式。它们可以轻松避免使用像 .float-left 这样的非语义类,并在库中分发样式集合。

Mixin 使用 @mixin at 规则定义,写作 @mixin <name> { ... }@mixin name(<arguments...>) { ... }。mixin 的名称可以是任何不以 -- 开头的 Sass 标识符,并且可以包含除 顶层声明 之外的任何 陈述。它们可用于封装可放入单个 样式规则 中的样式;它们可以包含自己的样式规则,这些规则可以嵌套在其他规则中或包含在样式表的顶层;或者它们只能用于修改变量。

¥Mixins are defined using the @mixin at-rule, which is written @mixin <name> { ... } or @mixin name(<arguments...>) { ... }. A mixin’s name can be any Sass identifier that doesn’t begin with --, and it can contain any statement other than top-level statements. They can be used to encapsulate styles that can be dropped into a single style rule; they can contain style rules of their own that can be nested in other rules or included at the top level of the stylesheet; or they can just serve to modify variables.

使用 @include at 规则将 Mixin 包含到当前上下文中,该规则写作 @include <name>@include <name>(<arguments...>),并包含 mixin 的名称。

¥Mixins are included into the current context using the @include at-rule, which is written @include <name> or @include <name>(<arguments...>), with the name of the mixin being included.

Playground

SCSS Syntax

@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;
}
Playground

Sass Syntax

@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 Output

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











💡 Fun fact:

Mixin 名称与所有 Sass 标识符一样,将连字符和下划线视为相同。这意味着 reset-listreset_list 都引用同一个 mixin。这是 Sass 早期的历史遗留问题,当时它只允许在标识符名称中使用下划线。一旦 Sass 添加了对连字符的支持以匹配 CSS 的语法,两者就变得等效以使迁移更容易。

¥Mixin names, like all Sass identifiers, treat hyphens and underscores as identical. This means that reset-list and reset_list both refer to the same mixin. This is a historical holdover from the very early days of Sass, when it only allowed underscores in identifier names. Once Sass added support for hyphens to match CSS’s syntax, the two were made equivalent to make migration easier.

参数参数 permalink

¥Arguments

¥

Mixin 还可以接受参数,这使得每次调用它们时都可以自定义它们的行为。参数在 @mixin 规则中的 mixin 名称后面指定,作为用括号括起来的变量名称列表。然后,mixin 必须以 SassScript 表达式 的形式包含相同数量的参数。这些表达式的值可在 mixin 的主体中作为相应的变量使用。

¥Mixins can also take arguments, which allows their behavior to be customized each time they’re called. The arguments are specified in the @mixin rule after the mixin’s name, as a list of variable names surrounded by parentheses. The mixin must then be included with the same number of arguments in the form of SassScript expressions. The values of these expression are available within the mixin’s body as the corresponding variables.

Playground

SCSS Syntax

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

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

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

Sass Syntax

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

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



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

CSS Output

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





💡 Fun fact:

参数列表也可以有尾随逗号!这使得在重构样式表时更容易避免语法错误。

¥Argument lists can also have trailing commas! This makes it easier to avoid syntax errors when refactoring your stylesheets.

可选参数可选参数 permalink

¥Optional Arguments

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

¥Normally, every argument a mixin declares must be passed when that mixin is included. However, you can make an argument optional by defining a default value which will be used if that argument isn’t passed. Default values use the same syntax as variable declarations: the variable name, followed by a colon and a SassScript expression. This makes it easy to define flexible mixin APIs that can be used in simple or complex ways.

Playground

SCSS Syntax

@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);
}
Playground

Sass Syntax

@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 Output

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







💡 Fun fact:

默认值可以是任何 SassScript 表达式,它们甚至可以引用之前的参数!

¥Default values can be any SassScript expression, and they can even refer to earlier arguments!

关键字参数关键字参数 permalink

¥Keyword Arguments

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

¥When a mixin is included, arguments can be passed by name in addition to passing them by their position in the argument list. This is especially useful for mixins with multiple optional arguments, or with boolean arguments whose meanings aren’t obvious without a name to go with them. Keyword arguments use the same syntax as variable declarations and optional arguments.

Playground

SCSS Syntax

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

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

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

Sass Syntax

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

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



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

CSS Output

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







⚠️ Heads up!

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

¥Because any argument can be passed by name, be careful when renaming a mixin’s arguments… it might break your users! It can be helpful to keep the old name around as an optional argument for a while and printing a warning if anyone passes it, so they know to migrate to the new argument.

采取任意参数采取任意参数 permalink

¥Taking Arbitrary Arguments

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

¥Sometimes it’s useful for a mixin to be able to take any number of arguments. If the last argument in a @mixin declaration ends in ..., then all extra arguments to that mixin are passed to that argument as a list. This argument is known as an argument list.

Playground

SCSS Syntax

@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");






Playground

Sass Syntax

@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 Output

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;
}

采用任意关键字参数采用任意关键字参数 permalink

¥Taking Arbitrary Keyword Arguments

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

¥Argument lists can also be used to take arbitrary keyword arguments. The meta.keywords() function takes an argument list and returns any extra keywords that were passed to the mixin as a map from argument names (not including $) to those arguments’ values.

Playground

SCSS Syntax

@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,
)
Playground

Sass Syntax

@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 Output

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

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

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







💡 Fun fact:

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

¥If you don’t ever pass an argument list to the meta.keywords() function, that argument list won’t allow extra keyword arguments. This helps callers of your mixin make sure they haven’t accidentally misspelled any argument names.

传递任意参数传递任意参数 permalink

¥Passing Arbitrary Arguments

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

¥Just like argument lists allow mixins to take arbitrary positional or keyword arguments, the same syntax can be used to pass positional and keyword arguments to a mixin. If you pass a list followed by ... as the last argument of an include, its elements will be treated as additional positional arguments. Similarly, a map followed by ... will be treated as additional keyword arguments. You can even pass both at once!

Playground

SCSS Syntax

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

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

Sass Syntax

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

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

💡 Fun fact:

因为 参数列表 会跟踪位置参数和关键字参数,所以你可以使用它将两者同时传递给另一个 mixin。这使得为 mixin 定义别名变得非常容易!

¥Because an argument list keeps track of both positional and keyword arguments, you use it to pass both at once to another mixin. That makes it super easy to define an alias for a mixin!

Playground

SCSS Syntax

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

Sass Syntax

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

内容块内容块 permalink

¥Content Blocks

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

¥In addition to taking arguments, a mixin can take an entire block of styles, known as a content block. A mixin can declare that it takes a content block by including the @content at-rule in its body. The content block is passed in using curly braces like any other block in Sass, and it’s injected in place of the @content rule.

Playground

SCSS Syntax

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

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

Sass Syntax

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



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


CSS Output

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






💡 Fun fact:

一个 mixin 可以包含多个 @content at 规则。如果是这样,内容块将单独包含在每个 @content 中。

¥A mixin can include multiple @content at-rules. If it does, the content block will be included separately for each @content.

⚠️ Heads up!

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

¥A content block is lexically scoped, which means it can only see local variables in the scope where the mixin is included. It can’t see any variables that are defined in the mixin it’s passed to, even if they’re defined before the content block is invoked.

将参数传递给内容块将参数传递给内容块 permalink

¥Passing Arguments to Content Blocks

兼容性:
Dart Sass
since 1.15.0
LibSass
Ruby Sass

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

¥A mixin can pass arguments to its content block the same way it would pass arguments to another mixin by writing @content(<arguments...>). The user writing the content block can accept arguments by writing @include <name> using (<arguments...>). The argument list for a content block works just like a mixin’s argument list, and the arguments passed to it by @content work just like passing arguments to a mixin.

⚠️ Heads up!

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

¥If a mixin passes arguments to its content block, that content block must declare that it accepts those arguments. This means that it’s a good idea to only pass arguments by position (rather than by name), and it means that passing more arguments is a breaking change.

如果你想灵活地传递给内容块的信息,请考虑向其传递包含可能需要的信息的 映射

¥If you want to be flexible in what information you pass to a content block, consider passing it a map that contains information it may need!

Playground

SCSS Syntax

@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;
    }
  }
}
Playground

Sass Syntax

@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 Output

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





缩进混入语法缩进混入语法 permalink

¥Indented Mixin Syntax

除了标准 @mixin@include 之外,缩进语法 还具有用于定义和使用 mixin 的特殊语法。Mixin 使用字符 = 定义,并使用 + 包含它们。尽管这种语法更简洁,但也较难一眼理解,因此鼓励用户避免使用它。

¥The indented syntax has a special syntax for defining and using mixins, in addition to the standard @mixin and @include. Mixins are defined using the character =, and they’re included using +. Although this syntax is terser, it’s also harder to understand at a glance and users are encouraged to avoid it.

Playground

Sass Syntax

=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 Output

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