@mixin 和 @include
Mixin 允许您定义可在整个样式表中重复使用的样式。它们让您轻松避免使用像 .float-left
这样的非语义类,并将样式集合分布在库中。
Mixin 使用 @mixin
at-rule 定义,写法为 @mixin <name> { ... }
或 @mixin name(<arguments...>) { ... }
。Mixin 的名称可以是任何不以 --
开头的 Sass 标识符,并且可以包含除 顶级语句 之外的任何 语句。它们可用于封装可以放入单个 样式规则 的样式;它们可以包含自己的样式规则,这些规则可以嵌套在其他规则中或包含在样式表的顶层;或者它们仅仅用于修改变量。
Mixin 使用 @include
at-rule 包含到当前上下文中,写法为 @include <name>
或 @include <name>(<arguments...>)
,其中包含 Mixin 的名称。
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;
}
💡 有趣的事实
Mixin 名称(与所有 Sass 标识符一样)将连字符和下划线视为相同。这意味着 reset-list
和 reset_list
都指向同一个 Mixin。这是 Sass 最初时期的历史遗留问题,那时它只允许在标识符名称中使用下划线。当 Sass 添加了对连字符的支持以匹配 CSS 的语法后,这两个符号被等效以简化迁移。
参数参数永久链接
Mixin 也可以接受参数,这允许在每次调用它们时自定义它们的行为。参数在 @mixin
规则中 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 表达式。这使得定义灵活的 Mixin 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 时,除了按参数列表中的位置传递参数之外,还可以按名称传递参数。这对于具有多个可选参数或具有 布尔值 参数(如果没有名称很难理解其含义)的 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;
}
⚠️ 注意!
因为任何参数都可以按名称传递,所以请谨慎重命名 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 的别名变得非常容易!
内容块内容块永久链接
除了接受参数之外,Mixin 还可以接受一个完整的样式块,称为内容块。Mixin 可以通过在其主体中包含 @content
at-rule 来声明它接受一个内容块。内容块使用花括号传递,就像 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
at-rule。如果它这样做,内容块将分别为每个 @content
包含。
⚠️ 注意!
内容块是词法作用域的,这意味着它只能看到 包含 Mixin 的作用域中的局部变量。它看不到传递给它的 Mixin 中定义的任何变量,即使这些变量是在调用内容块之前定义的。
向内容块传递参数向内容块传递参数永久链接
- Dart Sass
- 自 1.15.0 起
- LibSass
- ✗
- Ruby Sass
- ✗
Mixin 可以像传递给另一个 Mixin 一样向其内容块传递参数,方法是编写 @content(<arguments...>)
。编写内容块的用户可以通过编写 @include <name> using (<arguments...>)
来接受参数。内容块的参数列表与 Mixin 的参数列表的工作方式相同,传递给它的参数与传递给 Mixin 的参数的工作方式相同。
⚠️ 注意!
如果 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
之外,还有一种特殊的语法用于定义和使用 Mixin。Mixin 使用字符 =
定义,使用 +
包含。尽管这种语法更简洁,但它也更难理解,建议用户避免使用它。
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;
}