9. 混合指令 (Mixin Directives)

混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,比如 .float-left。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。

9.1. 定义混合指令 @mixin (Defining a Mixin: @mixin)

混合指令的用法是在 @mixin 后添加名称与样式,比如名为 large-text 的混合通过下面的代码定义:

  1. @mixin large-text {
  2. font: {
  3. family: Arial;
  4. size: 20px;
  5. weight: bold;
  6. }
  7. color: #ff0000;
  8. }

混合也需要包含选择器和属性,甚至可以用 & 引用父选择器:

  1. @mixin clearfix {
  2. display: inline-block;
  3. &:after {
  4. content: ".";
  5. display: block;
  6. height: 0;
  7. clear: both;
  8. visibility: hidden;
  9. }
  10. * html & { height: 1px }
  11. }

9.2. 引用混合样式 @include (Including a Mixin: @include)

使用 @include 指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选):

  1. .page-title {
  2. @include large-text;
  3. padding: 4px;
  4. margin-top: 10px;
  5. }

编译为

  1. .page-title {
  2. font-family: Arial;
  3. font-size: 20px;
  4. font-weight: bold;
  5. color: #ff0000;
  6. padding: 4px;
  7. margin-top: 10px; }

也可以在最外层引用混合样式,不会直接定义属性,也不可以使用父选择器。

  1. @mixin silly-links {
  2. a {
  3. color: blue;
  4. background-color: red;
  5. }
  6. }
  7. @include silly-links;

编译为

  1. a {
  2. color: blue;
  3. background-color: red; }

混合样式中也可以包含其他混合样式,比如

  1. @mixin compound {
  2. @include highlighted-background;
  3. @include header-text;
  4. }
  5. @mixin highlighted-background { background-color: #fc0; }
  6. @mixin header-text { font-size: 20px; }

混合样式中应该只定义后代选择器,这样可以安全的导入到文件的任何位置。

9.3. 参数 (Arguments)

参数用于给混合指令中的样式设定变量,并且赋值使用。在定义混合指令的时候,按照变量的格式,通过逗号分隔,将参数写进圆括号里。引用指令时,按照参数的顺序,再将所赋的值对应写进括号:

  1. @mixin sexy-border($color, $width) {
  2. border: {
  3. color: $color;
  4. width: $width;
  5. style: dashed;
  6. }
  7. }
  8. p { @include sexy-border(blue, 1in); }

编译为

  1. p {
  2. border-color: blue;
  3. border-width: 1in;
  4. border-style: dashed; }

混合指令也可以使用给变量赋值的方法给参数设定默认值,然后,当这个指令被引用的时候,如果没有给参数赋值,则自动使用默认值:

  1. @mixin sexy-border($color, $width: 1in) {
  2. border: {
  3. color: $color;
  4. width: $width;
  5. style: dashed;
  6. }
  7. }
  8. p { @include sexy-border(blue); }
  9. h1 { @include sexy-border(blue, 2in); }

编译为

  1. p {
  2. border-color: blue;
  3. border-width: 1in;
  4. border-style: dashed; }
  5. h1 {
  6. border-color: blue;
  7. border-width: 2in;
  8. border-style: dashed; }

9.3.1. 关键词参数 (Keyword Arguments)

混合指令也可以使用关键词参数,上面的例子也可以写成:

  1. p { @include sexy-border($color: blue); }
  2. h1 { @include sexy-border($color: blue, $width: 2in); }

虽然不够简明,但是阅读起来会更方便。关键词参数给函数提供了更灵活的接口,以及容易调用的参数。关键词参数可以打乱顺序使用,如果使用默认值也可以省缺,另外,参数名被视为变量名,下划线、短横线可以互换使用。

9.3.2. 参数变量 (Variable Arguments)

有时,不能确定混合指令需要使用多少个参数,比如一个关于 box-shadow 的混合指令不能确定有多少个 'shadow' 会被用到。这时,可以使用参数变量 声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理:

  1. @mixin box-shadow($shadows...) {
  2. -moz-box-shadow: $shadows;
  3. -webkit-box-shadow: $shadows;
  4. box-shadow: $shadows;
  5. }
  6. .shadows {
  7. @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
  8. }

编译为

  1. .shadowed {
  2. -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  3. -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  4. box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  5. }

参数变量也可以用在引用混合指令的时候 (@include),与平时用法一样,将一串值列表中的值逐条作为参数引用:

  1. @mixin colors($text, $background, $border) {
  2. color: $text;
  3. background-color: $background;
  4. border-color: $border;
  5. }
  6. $values: #ff0000, #00ff00, #0000ff;
  7. .primary {
  8. @include colors($values...);
  9. }

编译为

  1. .primary {
  2. color: #ff0000;
  3. background-color: #00ff00;
  4. border-color: #0000ff;
  5. }
You can use variable arguments to wrap a mixin and add additional styles without changing the argument signature of the mixin. If you do so, even keyword arguments will get passed through to the wrapped mixin. For example:
  1. @mixin wrapped-stylish-mixin($args...) {
  2. font-weight: bold;
  3. @include stylish-mixin($args...);
  4. }
  5. .stylish {
  6. // The $width argument will get passed on to "stylish-mixin" as a keyword
  7. @include wrapped-stylish-mixin(#00ff00, $width: 100px);
  8. }

上面注释内的意思是:$width 参数将会传递给 stylish-mixin 作为关键词。

9.4. 向混合样式中导入内容 (Passing Content Blocks to a Mixin)

在引用混合样式的时候,可以先将一段代码导入到混合指令中,然后再输出混合样式,额外导入的部分将出现在 @content 标志的地方:

  1. @mixin apply-to-ie6-only {
  2. * html {
  3. @content;
  4. }
  5. }
  6. @include apply-to-ie6-only {
  7. #logo {
  8. background-image: url(/logo.gif);
  9. }
  10. }

编译为

  1. * html #logo {
  2. background-image: url(/logo.gif);
  3. }

为便于书写,@mixin 可以用 = 表示,而 @include 可以用 + 表示,所以上面的例子可以写成:

  1. =apply-to-ie6-only
  2. * html
  3. @content
  4. +apply-to-ie6-only
  5. #logo
  6. background-image: url(/logo.gif)

注意:@content 在指令中出现过多次或者出现在循环中时,额外的代码将被导入到每一个地方。

9.4.1. Variable Scope and Content Blocks

The block of content passed to a mixin are evaluated in the scope where the block is defined, not in the scope of the mixin. This means that variables local to the mixin cannot be used within the passed style block and variables will resolve to the global value:
  1. $color: white;
  2. @mixin colors($color: blue) {
  3. background-color: $color;
  4. @content;
  5. border-color: $color;
  6. }
  7. .colors {
  8. @include colors { color: $color; }
  9. }

编译为

  1. .colors {
  2. background-color: blue;
  3. color: white;
  4. border-color: blue;
  5. }
Additionally, this makes it clear that the variables and mixins that are used within the passed block are related to the other styles around where the block is defined. For example:
  1. #sidebar {
  2. $sidebar-width: 300px;
  3. width: $sidebar-width;
  4. @include smartphone {
  5. width: $sidebar-width / 3;
  6. }
  7. }