Sass(SCSS)中文手册——语法

大纲

1、嵌套规则(Nested Rules)
2、父选择符: &
3、嵌套属性
4、SassScript
5、@ 规则和指令
6、控制指令(Control Directives)
7、Mixin Directives
8、Function Directives

1、嵌套规则(Nested Rules)

Sass允许CSS规则相互嵌套。内部规则只应用于外部规则的选择器。
这有助于避免重复父选择器,并使具有许多嵌套选择器的复杂CSS布局更加简单。

#main {
  width: 97%;
  p,
  div {
    font-size: 2em;
    a {
      font-weight: bold;
    }
  }
  pre {
    font-size: 3em;
  }
}
/*
    scss编译为:css语法
*/
#main {
  width: 97%;
}
#main p,
#main div {
  font-size: 2em;
}
#main p a,
#main div a {
  font-weight: bold;
}
#main pre {
  font-size: 3em;
}
2、父选择符: &

当选择器拥有某种特殊效果(如悬停)或者父选择器有特定类的时候,需要对这些情况设置某种样式,在这些情况下,可以使用&字符显式指定应该插入父选择器的位置。
& 在编译时将被替换为父选择符,输出到 CSS 中。 也就是说,如果你有一个深层嵌套的规则,父选择符也会在 & 被替换之前被完整的解析。

#main {
  color: black;
  a {
    font-weight: bold;
    &:hover {
      color: red;
    }
  }
}
/*
    编译为
*/
#main {
  color: black;
}
#main a {
  font-weight: bold;
}
#main a:hover {
  color: red;
}
3、嵌套属性

CSS有相当多的属性位于“名称空间”中;
例如,font-family、font-size和font-weight都位于font(字体)名称空间中。
在CSS中,如果想在相同的名称空间中设置一些属性,每次都必须键入它。Sass为此提供了一个快捷方式:只需编写一次名称空间,然后在其中嵌套每个子属性。

/*
    scss
*/
.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}
/*
    编译为:
*/
.funky {
  font-family: fantasy;
  font-size: 30em;
  font-weight: bold;
}
4、SassScript

除了普通的CSS属性语法,Sass还支持一组名为SassScript的扩展。

SassScript允许属性使用变量、算术和其他函数。SassScript可以用于任何属性值。
SassScript还可以用来生成选择器和属性名,这在编写mixin时非常有用。这是通过插值来实现的。

4.1、算术
>> "Hello, Sassy World!"
"Hello, Sassy World!"
>> 1px + 1px + 1px
3px
>> #777 + #777
#eeeeee
>> #777 + #888
white
4.2、Variables(变量): $
/*
    使用SassScript最直接的方法是使用变量。变量以美元符号开头,设置类似CSS属性
*/
$width: 5em;
/*
    然后你可以在属性中引用它们:
*/
#main {
  width: $width;
}
/*
    变量只能在定义变量的嵌套选择器级别内可用。如果它们是在任何嵌套选择器之外定义的,
那么它们在任何地方都是可用的。
*/
4.3、函数
/*
    SassScript 定义了一些有用的函数, 这些函数可以像普通 CSS 函数语法一样被调用:
*/
p {
  color: hsl(0, 100%, 50%);
}
/*
    被编译为:
*/
p {
  color: #ff0000;
}
/*
    关键词参数:
        Sass 函数允许指定明确的关键词参数 (keyword arguments) 进行调用。 
        虽然不够简明,但可以让样式表阅读起来会更方便。 关键词参数让函数具有更灵活的接口,
即便参数众多,也不会让使用变得困难。
        命名参数(named arguments)可以以任意顺序传入,并且,具有默认值的参数可以省略掉。 
由于命名参数也是变量名称,因此,下划线、短横线可以交换使用。
*/
/*
    上面的例子也可以写成:
*/
p {
  color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);
}
4.4、Interpolation(插值): #{}
/*
    可以在选择器和属性名中使用SassScript变量,使用#{}插值语法:
*/
$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
}
/*
    被编译为:
*/
p.foo {
  border-color: blue;
}
4.5、变量默认值: !default
/*
    你可以在变量尚未赋值前,通过在值的末尾处添加 !default 标记来为其指定。 也就是说,
如果该变量已经被赋值, 就不会再次赋值, 但是,如果还没有被赋值,就会被指定一个值。
*/
$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;

#main {
  content: $content;
  new-content: $new_content;
}
/*
    被编译为:
*/
#main {
  content: "First content";
  new-content: "First time reference";
}

/*
    变量的值如果是 null 的话,会被 !default 当做没有值:
*/
$content: null;
$content: "Non-null content" !default;

#main {
  content: $content;
}
/*
    被编译为:
*/
#main {
  content: "Non-null content";
}
5、@ 规则和指令

Sass 支持所有 CSS3 的 @ 规则, 以及一些 Sass 专属的规则,也被称为“指令(directives)”。 这些规则在 Sass 中具有不同的功效。

5.1、@import

Sass 扩展了 CSS 的 @import 规则,让它能够引入 SCSS 和 Sass 文件。 所有引入的 SCSS 和 Sass 文件都会被合并并输出一个单一的 CSS 文件。 另外,被导入的文件中所定义的变量或 mixins 都可以在主文件中使用。

@import 根据文件名引入。 默认情况下,它会寻找 Sass 文件并直接引入, 但是,在少数几种情况下,它会被编译成 CSS 的 @import 规则:
i:如果文件的扩展名是 .css。
ii:如果文件名以 http:// 开头。
iii:如果文件名是 url()。
iv:如果 @import 包含了任何媒体查询(media queries)。
如果上述情况都没有出现,并且扩展名是 .scss 或 .sass, 该名称的 Sass 或 SCSS 文件就会被引入。 如果没有扩展名, Sass 将试着找出具有 .scss 或 .sass 扩展名的同名文件并将其引入。

/*
    两者都将引入 foo.scss 文件
*/
@import "foo.scss";
@import "foo";
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);
/*
    将被编译为:
*/
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);
/*
    也可以通过一个 @import 引入多个文件。
*/
@import "rounded-corners", "text-shadow";
/*
    将引入 rounded-corners 和 text-shadow 两个文件。
*/
5.2、片段

如果你有一个 SCSS 或 Sass 文件需要引入, 但是你又不希望它被编译为一个 CSS 文件, 这时,你就可以在文件名前面加一个下划线,就能避免被编译。 这将告诉 Sass 不要把它编译成 CSS 文件。 然后,你就可以像往常一样引入这个文件了,而且还可以省略掉文件名前面的下划线。

/*
    例如,你有一个文件叫做 _colors.scss。 这样就不会生成 _colors.css 文件了 
    而且你还可以这样做:
*/
@import "colors";
/*
    来引入 _colors.scss 文件。
*/

注意,在同一个目录不能同时存在带下划线和不带下划线的同名文件。 例如, _colors.scss 不能与 colors.scss 并存。

5.3、嵌套 @import

虽然大部分时间只需在顶层文件使用 @import 就行了, 但是,你还可以把他们包含在 CSS 规则 和 @media 规则中。

/*example.scss*/
.example {
  color: red;
}
/* use */
#main {
  @import "example";
}
/* 编译为 */
#main .example {
  color: red;
}
5.4、@media

Sass中的@media指令就像普通CSS中的指令一样,有一个额外的功能:它们可以嵌套在CSS规则中。如果@media指令出现在CSS规则中,它将冒泡到样式表的顶层,将所有选择器放到规则中。这使得添加特定于媒体的样式变得很容易,而无需重复选择器或中断样式表的流程。

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
  .header {
    width: 300px;
    @media screen and (orientation: landscape) {
      width: 500px;
    }
  }
}
/* 编译为: */
.sidebar {
  width: 300px;
}
@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px;
  }
}
.sidebar .header {
  width: 300px;
}
@media screen and (orientation: landscape) {
  .sidebar .header {
    width: 500px;
  }
}

@media查询也可以相互嵌套。然后将使用and操作符组合查询。

@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}
/* 编译为: */
@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px;
  }
}

@media查询可以包含SassScript表达式(包括变量、函数和操作符)来代替特性名称和特性值。

$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;

@media #{$media} and ($feature: $value) {
  .sidebar {
    width: 500px;
  }
}
/* 编译为: */
@media screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .sidebar {
    width: 500px;
  }
}
5.5、@extend

在设计页面时,经常会遇到这样的情况:一个类应该拥有另一个类的所有样式,以及它自己的特定样式。处理这个问题最常见的方法是在HTML中使用更通用的类和更特定的类。

/*
  例如,假设我们有一个针对正常错误和严重错误的设计。我们可以这样写我们的标记:
*/
<div class="error seriousError">
  Oh no! You've been hacked!
</div>

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  border-width: 3px;
}
/*
    不幸的是,这意味着我们必须始终记住在. seriouserror中使用.error。这是一个维护负担,
会导致一些棘手的bug,并可能将非语义样式的关注点引入标记。

    @extend指令通过告诉Sass一个选择器应该继承另一个选择器的样式来避免这些问题。
*/
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
/* 编译为: */
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd;
}

.seriousError {
  border-width: 3px;
}

/*
    这意味着,除了. seriouserror特有的样式外,为.error定义的所有样式也应用于. seriouserror
实际上,每个拥有类. seriouserror的元素都有类.error。
*/
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
/* 编译为: */
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.error.intrusion, .seriousError.intrusion {
  background-image: url("/image/hacked.png"); }

.seriousError {
  border-width: 3px;
}
5.5.1、复杂选择器的继承(Extending Complex Selectors)
/*
    类选择器不是惟一可以扩展的东西。可以扩展只涉及单个元素的任何选择器,
例如 .special.cool, a:hover, or a.user[href^="http://"]
*/
.hoverlink {
  @extend a:hover;
}
/*
    与类一样,这意味着为a:hover定义的所有样式也应用于.hoverlink。
*/
.hoverlink {
  @extend a:hover;
}
a:hover {
  text-decoration: underline;
}
/* 被编译为: */
a:hover, .hoverlink {
  text-decoration: underline;
}

/*
    就像上面的.error.intrusion一样,任何使用:hover的规则也适用于.hoverlink,
即使它们也有其他选择器。
*/
.hoverlink {
  @extend a:hover;
}
.comment a.user:hover {
  font-weight: bold;
}
/* 被编译为: */
.comment a.user:hover,
.comment .user.hoverlink {
  font-weight: bold;
}
5.5.2、多继承(Multiple Extends)
/*
    单个选择器可以扩展多个选择器。这意味着它继承了所有扩展选择器的样式。
*/
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}
/* 编译为:*/
.error,
.seriousError {
  border: 1px #f00;
  background-color: #fdd;
}

.attention,
.seriousError {
  font-size: 3em;
  background-color: #ff0;
}

.seriousError {
  border-width: 3px;
}
/*
    实际上,每个带有类.seriouserror的元素都有类.error和类.attention。
因此,文档中稍后定义的样式优先:.seriouserror的背景色是#ff0,而不是#fdd,
因为.attention是在.error之后定义的。

    还可以使用逗号分隔的选择器列表编写多个扩展。
例如@extend .error,.attention与@extend .error;@extend.attention相同。
*/
5.5.3、链接扩展(Chaining Extends)
/*
    一个选择器可以扩展另一个选择器,而另一个选择器又可以扩展第三个选择器。
*/
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
.criticalError {
  @extend .seriousError;
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}

/* 编译为:*/
.error,
.seriousError,
.criticalError {
  border: 1px #f00;
  background-color: #fdd;
}

.seriousError,
.criticalError {
  border-width: 3px;
}

.criticalError {
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}
5.5.4、选择器序列(Selector Sequences)
/*
    选择器序列,例如.foo .bar或.foo + .bar,目前无法扩展。
但是,嵌套选择器本身也可以使用@extend。
*/
#fake-links .link {
  @extend a;
}

a {
  color: blue;
  &:hover {
    text-decoration: underline;
  }
}
/* 编译为:*/
a,
#fake-links .link {
  color: blue;
}
a:hover,
#fake-links .link:hover {
  text-decoration: underline;
}
5.5.5、合并选择序列

有时选择器序列会扩展另一个序列中出现的另一个选择器。在这种情况下,这两个序列需要合并。
虽然在技术上可以生成所有可能匹配这两个序列的选择器,但是这会使样式表太大。例如,上面的简单示例需要10个选择器。相反,Sass只生成可能有用的选择器。

/*
    当合并的两个序列没有共同的选择器时,就会生成两个新的选择器:一个在第二个序列之前有
第一个序列,另一个在第一个序列之前有第二个序列。
*/
#admin .tabbar a {
  font-weight: bold;
}
#demo .overview .fakelink {
  @extend a;
}
/* 编译为 */
#admin .tabbar a,
#admin .tabbar #demo .overview .fakelink,
#demo .overview #admin .tabbar .fakelink {
  font-weight: bold;
}

/*
    如果两个序列确实共享一些选择器,那么这些选择器将合并在一起,只有差异(如果仍然存在的话)
将交替出现。在本例中,两个序列都包含id #admin,因此生成的选择器将合并这两个id:
*/
#admin .tabbar a {
  font-weight: bold;
}
#admin .overview .fakelink {
  @extend a;
}
/* 编译为: */
#admin .tabbar a,
#admin .tabbar .overview .fakelink,
#admin .overview .tabbar .fakelink {
  font-weight: bold;
}
5.5.6、只继承选择器(@extend-Only Selectors)

有时候,您会为一个类编写样式,而这个类只需要@extend,而不需要直接在HTML中使用。在编写Sass库时尤其如此,如果用户需要,您可以为他们提供@extend样式,如果用户不需要,您可以忽略。
如果为此使用普通类,那么在生成样式表时就会创建许多额外的CSS,并有可能与HTML中使用的其他类发生冲突。这就是为什么Sass支持“占位符选择器”(例如%foo)。
占位符选择器看起来像类和id选择器,除了 # or . 替换为%。它们可以在类或id可以使用的任何地方使用,并且它们本身可以防止规则集被呈现到CSS。

/* This ruleset won't be rendered on its own. */
#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}
/*
    但是,占位符选择器可以扩展,就像类和id一样。将生成扩展的选择器,
但不会生成基本占位符选择器。
*/
.notice {
  @extend %extreme;
}
/*
    以上单独存在没有效果,Sass也不会编译出来,只有两者共同存在才会进行编译,
    简单的理解就是:类notice继承了#context a的类,或者可以理解为notice在#context a的基础上
扩展
*/
#context a.notice {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}
5.5.7、可选标志(The !optional Flag)

通常在扩展选择器时,如果@extend不起作用,就会出现错误。例如,如果你写a.important{@extend .notice},如果没有包含.notice的选择器,这是一个错误。如果唯一包含.notice的选择器是h1,这也是一个错误。注意,由于h1与a冲突,因此不会生成新的选择器。
但是,有时您希望允许@extend不产生任何新的选择器。为此,只需在选择器之后添加!optional标志。

// 不加 !optional 会报错
a.important {
  @extend .notice !optional;
}
a.important {
  @extend .notice!optional;
}

h1.notice {
  color: red;
}
/* 编译为*/
h1.notice {
  color: red;
}
// 注意.notice是h1标签上的,与下面的代码是有区别的
a.important {
  @extend .notice!optional;
}
h1 .notice {
  color: red;
}
/* 编译为:*/
h1 .notice, h1 a.important {
  color: red;
}
5.5.8、指令中的继承(@extend in Directives)

在@media等指令中使用@extend有一些限制。Sass无法使@media块之外的CSS规则应用于它内部的选择器,除非通过到处复制样式来创建大量样式表膨胀。这意味着如果你在@media(或其他CSS指令)中使用@extend,你只能扩展出现在同一个指令块中的选择器。

/* 正确使用 */
@media print {
  .error {
    border: 1px #f00;
    background-color: #fdd;
  }
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}
/* 错误使用 */
.error {
  border: 1px #f00;
  background-color: #fdd;
}

@media print {
  .seriousError {
    // INVALID EXTEND: .error is used outside of the "@media print" directive
    @extend .error;
    border-width: 3px;
  }
}
5.6、@debug

@debug指令将SassScript表达式的值打印到标准错误输出流。它对于调试具有复杂SassScript的Sass文件非常有用。

@debug 10em + 12em;
/* outputs: */
Line 1 DEBUG: 22em
5.7、@warn

@warn指令将SassScript表达式的值打印到标准错误输出流。对于需要提醒用户注意弃用或从轻微混合使用错误中恢复的库,它非常有用。@warn和@debug之间有两个主要区别:
1、您可以使用 ——quiet命令行选项或:quiet Sass选项关闭警告。
2、样式表跟踪将与消息一起打印出来,以便被警告的用户可以看到他们的样式在哪里引起警告。

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @warn "Assuming #{$x} to be in pixels";
    $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
    $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}
6、控制指令(Control Directives)

SassScript支持基本的控制指令,用于只在某些条件下包含样式,或者多次包含相同的样式,并带有变体。
注意,控制指令是一个高级特性,在日常样式化过程中不推荐使用。它们主要用于mixin中,特别是那些属于Compass这样的库的部分,因此需要很大的灵活性。

6.1、@if
/*
    @if指令使用SassScript表达式,如果表达式返回的不是false或null,则使用嵌套在其下的样式:
*/
p {
  @if 1 + 1 == 2 { border: 1px solid;  }
  @if 5 < 3      { border: 2px dotted; }
  @if null       { border: 3px double; }
}
/* 编译为 */
p {
  border: 1px solid;
}

/*
    @if语句后面可以跟着几个@else if语句和一个@else语句。
如果@if语句失败,则按顺序尝试@else If语句,直到成功或到达@else为止。例如:
*/
$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
/* 编译为: */
p {
  color: green;
}
6.2、@for
/*
    for指令重复输出一组样式。对于每个重复项,计数器变量用于调整输出。
    这个指令有两种形式:@for $var,从<start>到<end>; @for $var,从<start>到<end>。
    注意关键字through和to的区别。
    $var可以是任何变量名,比如$i;
    <start>和<end>是应该返回整数的SassScript表达式。

    @for语句将$var设置为指定范围内的每个连续数字,每次使用$var的值输出嵌套样式。
    对于from ... through,范围包括<start>和<end>的值,
    但是from ... to,范围运行到但不包括<end>的值。
*/
@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}
/* 编译为 */
.item-1 {
  width: 2em;
}
.item-2 {
  width: 4em;
}
.item-3 {
  width: 6em;
}
6.3、@each
/*
    $var可以是任何变量名,比如$length或$name,它是一个返回列表的SassScript表达式。

    @each规则将$var设置为列表中的每个项目,然后使用$var的值输出它包含的样式。例如:
*/
@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url("/images/#{$animal}.png");
  }
}

/* 编译为: */

.puma-icon {
  background-image: url("/images/puma.png");
}
.sea-slug-icon {
  background-image: url("/images/sea-slug.png");
}
.egret-icon {
  background-image: url("/images/egret.png");
}
.salamander-icon {
  background-image: url("/images/salamander.png");
}
6.4、@while
/*
    while指令接受一个SassScript表达式并重复输出嵌套样式,直到语句计算为false为止。
这可以用来实现比@for语句更复杂的循环,尽管这很少是必需的。例如:
*/
$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}

/* 编译为: */
.item-6 {
  width: 12em;
}

.item-4 {
  width: 8em;
}

.item-2 {
  width: 4em;
}
7、Mixin Directives

mixin允许您定义可以在整个样式表中重用的样式,而不需要求助于.float-left之类的非语义类。mixin还可以包含完整的CSS规则,以及Sass文档中其他任何允许的内容。它们甚至可以使用参数,允许您使用非常少的混合创建各种风格。

7.1、定义一个Mixin:Defining a Mixin: @mixin
/*
    mixin是用@mixin指令定义的。后面是mixin的名称和可选的参数,以及包含mixin内容的块。
例如,large-text Mixin的定义如下:
*/
@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

/*
    mixin也可能包含选择器,可能与属性混合。选择器甚至可以包含父引用。例如:
*/
@mixin clearfix {
  display: inline-block;
  &:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }
  * html & {
    height: 1px;
  }
}
7.2、引入一个Mixin:Including a Mixin: @include
/*
    mixin包含在带有@include指令的文档中。它接受mixin的名称和可选的参数,
并将由mixin定义的样式包含到当前规则中。例如:
*/
.page-title {
  @include large-text;
  padding: 4px;
  margin-top: 10px;
}
/*编译为:*/
.page-title {
  font-family: Arial;
  font-size: 20px;
  font-weight: bold;
  color: #ff0000;
  padding: 4px;
  margin-top: 10px;
}

/*
    只要mixin不直接定义任何属性或使用任何父引用,
它也可以包含在任何规则之外(即在文档的根目录下)。例如:
*/
@mixin silly-links {
  a {
    color: blue;
    background-color: red;
  }
}

@include silly-links;
/* 编译为 */
a {
  color: blue;
  background-color: red;
}
/*
    Mixin定义还可以包括其他Mixin。例如:
*/
@mixin compound {
  @include highlighted-background;
  @include header-text;
}

@mixin highlighted-background { background-color: #fc0; }
@mixin header-text { font-size: 20px; }
/*
    Mixin不得直接或间接地包括其本身。也就是说,mixin递归是禁止的。

    仅定义派生选择器的mixin可以安全地混合到文档的最顶层。
*/
7.3、参数:Arguments
/*
    mixin可以将参数SassScript值作为参数,这些参数在包含mixin时给出,
并在mixin中作为变量提供。

    在定义mixin时,参数被写成由逗号分隔的变量名,所有参数都放在名称后面的括号中。然后,
在包含mixin时,可以以相同的方式传入值。例如:
*/
@mixin sexy-border($color, $width) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}

p {
  @include sexy-border(blue, 1in);
}

/* 编译为 */
p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed;
}

/*
    mixin还可以使用常规的变量设置语法为其参数指定默认值。然后,当包含mixin时,
如果它没有传入该参数,则将使用默认值。例如:
*/
@mixin sexy-border($color, $width: 1in) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p {
  @include sexy-border(blue);
}
h1 {
  @include sexy-border(blue, 2in);
}
/* 编译为 */
p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed;
}

h1 {
  border-color: blue;
  border-width: 2in;
  border-style: dashed;
}

/*
    关键字参数

    还可以使用显式关键字参数包含mixin。例如,我们上面的例子可以写成:
*/
@mixin sexy-border($color, $width: 1in) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p {
  @include sexy-border($color: blue);
}
h1 {
  @include sexy-border($color: blue, $width: 2in);
}
/*
    虽然这不够简洁,但可以使样式表更易于阅读。它还允许函数提供更灵活的接口,
提供许多参数,而不会变得难以调用。
    命名参数可以按任何顺序传递,具有默认值的参数可以省略。
由于命名参数是变量名,下划线和破折号可以互换使用。
*/
7.4、变量参数
/*
    有时mixin接受数量未知的参数是有意义的。例如,用于创建框阴影的mixin可以将任意数量的阴影
作为参数。对于这些情况,Sass支持“变量参数”,它是mixin声明末尾的参数,它将所有剩余的参数打包
成一个列表。这些参数看起来会像正常的参数一样,只要这些参数以...为结尾,例如:
*/
@mixin box-shadow($shadows...) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}

.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
/* 编译为: */
.shadows {
  -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}

/*
    在调用mixin时也可以使用变量参数。使用相同的语法,您可以展开一个值列表,
以便将每个值作为单独的参数传递。例如:
*/
@mixin colors($text, $background, $border) {
  color: $text;
  background-color: $background;
  border-color: $border;
}

$values: #ff0000, #00ff00, #0000ff;
.primary {
  @include colors($values...);
}
/* 编译为 */
.primary {
  color: #ff0000;
  background-color: #00ff00;
  border-color: #0000ff;
}

/*
    您可以使用变量参数来包装mixin并添加其他样式,而无需更改mixin的参数签名。如果这样做,
甚至关键字参数也会传递到包装的mixin。例如:
*/
@mixin wrapped-stylish-mixin($args...) {
  font-weight: bold;
  @include stylish-mixin($args...);
}

.stylish {
  // The $width argument will get passed on to "stylish-mixin" as a keyword
  @include wrapped-stylish-mixin(#00ff00, $width: 100px);
}
7.5、将内容块传递给Mixin(Passing Content Blocks to a Mixin)
/*
    可以将一个样式块传递给mixin,以便将其放置在mixin包含的样式中。样式将出现在mixin中找到
的任何@content指令的位置。这使得定义与选择器和指令的构造相关的抽象成为可能。
*/
@mixin apply-to-ie6-only {
  * html {
    @content;
  }
}
@include apply-to-ie6-only {
  #logo {
    background-image: url(/logo.gif);
  }
}
/* 编译为: */
* html #logo {
  background-image: url(/logo.gif);
}

/*
    可以使用.sass简写语法进行相同的混合:
*/
=apply-to-ie6-only
  * html
    @content

+apply-to-ie6-only
  #logo
    background-image: url(/logo.gif)
/*
    注意:当@content指令不止一次指定或在循环中指定时,样式块将在每次调用时复制。
*/
/*
    可变范围和内容块

    传递给mixin的内容块是在定义该块的范围内计算的,而不是在mixin的范围内。
这意味着mixin的局部变量不能在传递的样式块中使用,变量将解析为全局值:
*/
$color: white;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors {
    color: $color;
  }
}
/* 编译为:*/
.colors {
  background-color: blue;
  color: white;
  border-color: blue;
}
/*
    此外,这清楚地表明,在传递的块中使用的变量和mixin与定义块的其他样式相关。例如:
*/
#sidebar {
  $sidebar-width: 300px;
  width: $sidebar-width;
  @include smartphone {
    width: $sidebar-width / 3;
  }
}
8、Function Directives
/*
    可以在sass中定义自己的函数,并在任何值或脚本上下文中使用它们。例如:
*/
$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar {
  width: grid-width(5);
}
/* 编译为: */
#sidebar {
  width: 240px;
}

/*
    正如您所看到的,函数可以访问任何全局定义的变量,也可以像mixin一样接受参数。
函数可能包含多个语句,必须调用@return来设置函数的返回值。

    与mixin一样,您可以使用关键字参数调用sass定义的函数。在上面的例子中,
我们可以这样调用这个函数:
*/
#sidebar {
  width: grid-width($n: 5);
}
/*
    建议在函数前面加上前缀,以避免命名冲突,以便样式表的读者知道它们不是Sass或CSS的一部分。
例如,如果您为ACME Corp工作,您可能会将该函数命名为-acme-grid-width以上的函数。

    用户定义的函数也以与mixin相同的方式支持变量参数。
*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,312评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,578评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,337评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,134评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,161评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,303评论 1 280
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,761评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,421评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,609评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,450评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,504评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,194评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,760评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,836评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,066评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,612评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,178评论 2 341

推荐阅读更多精彩内容