本文的内容主要来自于 Sass 的文档,但并不是对其进行直接翻译,根据自己的理解对其进行了一些增减和修改。同时通过对比式的排版,也更容易看清楚 Sass 到 CSS 之间的转换。
如果你发现有错误或者有其他建议可以到GitHub上告诉我,或者提交PR。
通过下图可以了解 CSS 语法中的一些名词。本文提及这些名词时,也会直接用其英文名称。
Sass 是 Syntactically Awesome StyleSheets 的缩写,它在原生 CSS 语法的基础上,提供了很多额外的功能,比如变量,规则嵌套, mixin 等等,并且完全兼容 CSS 的原有语法。Sass 的存在,让写 CSS 变的简单和有趣。
Sass 有两种语法。一种是 SCSS(Sassy CSS),它是对CSS 原有语法的扩展,也就是说一个 CSS 文件,也是一个有效的 SCSS 文件。使用这种语法的文件通常使用.scss
作为扩展名。本文主要以 SCSS 为主。
还有一种是 缩进式语法(直接叫Sass),其语法简洁,使用代码的缩进,代替大括号,来表示 CSS selector 的层级嵌套关系。每条规则后的分号,也被省略去。使用这种语法的文件通常使用.sass
作为扩展名。
这里是一个使用 gulp-sass
插件的例子。
var gulp = require('gulp'),
sass = require('gulp-sass');
gulp.task('sass', () => {
gulp.src('*.scss')
.pipe(sass({
outputStyle: 'expanded'
})).on('error', sass.logError)
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['sass']);
Sass 允许 CSS 规则进行嵌套。这可能是 Sass 最常用的功能了。
#main p {
color: #f3f3f3;
.redbox {
background-color: #ff0000;
}
}
#main p {
color: #f3f3f3;
}
#main p .redbox {
background-color: #ff0000;
}
这样在写规则的时候就不用每次都要重复写父级 selector,这使得包含很多层嵌套的复杂 CSS layout 变的简单。比如:
#main {
width: 97%;
p, div {
font-size: 2em;
a { font-weight: bold; }
}
pre { font-size: 3em; }
}
#main {
width: 97%;
}
#main p, #main div {
font-size: 2em;
}
#main p a, #main div a {
font-weight: bold;
}
#main pre {
font-size: 3em;
}
在 selector 内部,可以使用 &
符号来引用 父级 selector。比如:
.awesome-link {
color: blue;
&:hover {
color: red;
}
}
.post {
font-size: 1em;
&-head {
font-size: 1.8em;
}
}
.awesome-link {
color: blue;
}
.awesome-link:hover {
color: red;
}
.post {
font-size: 1em;
}
.post-head {
font-size: 1.8em;
}
CSS 中有一些属性存在于「命名空间」中,比如font-family
, font-size
, font-weight
都存在于 font
这个命名空间中。对于类似这样的属性,Sass 提供了一种快捷写法。注意下面例子中font
后面的冒号:
/*
* Nested Properties
*/
.funky {
font: {
family: Monaco;
size: 0.9em;
weight: bold;
}
}
/*
* Nested Properties
*/
.funky {
font-family: Monaco;
font-size: 0.9em;
font-weight: bold;
}
Sass 支持标准 CSS 中的多行注释,另外也支持 单行注释。
注意,在默认情况下生成的 CSS 中,多行注释会被保留,单行注释会被去除。
/*
* 这是一个多行注释
* 会被保留在生成的 CSS 中
*/
body {
color: black;
}
// 这是一个单行注释
// 会被移除
a {
color: green;
}
/*
* 这是一个多行注释
* 会被保留在生成的 CSS 中
*/
body {
color: black;
}
a {
color: green;
}
Sass 中可以使用变量。定义变量就像写 CSS 规则一样,只是前面要加上美元符号($
)。使用变量的时候,也是在变量名前面加上 $
。
仔细对比下面的 Sass 及其 CSS 输出。
$width: 5em;
#main {
width: $width;
}
#main {
width: 5em;
}
Sass 变量也是有作用域的。比如:
.s1 {
$width: 800px;
width: $width;
}
.s2 {
$width: 5em;
width: $width;
}
.s1 {
width: 800px;
}
.s2 {
width: 5em;
}
Sass 支持7种数据类型:
1.2
,12
,10px
"foo"
, 'bar'
, baz
blue
, #04a3f9
, rgba(255, 0, 0, 0.5)
true
, false
null
1.5em 1em 0 2em
, Helvetica, Arial, sans-serif
(key1: value1, key2: value2)
通常,Sass 转换成 CSS 的时候,字符串会保留原来的样子,即如果在 Sass 有引号,则生成的 CSS 中也会有引号,Sass 中没有引号,则 CSS 中也不会有引号。
TODO interpolation
在下面例子中,10px 15px 0 0
和 Helvetica, Arial, sans-serif
就是一个 Sass 列表。Sass 列表由空格或逗号隔开。
.demo {
margin: 10px 15px 0 0;
font-face: Helvetica, Arial, sans-serif;
}
$margin: 10px 20px 30px 10px;
.list-func-demo {
margin-bottom: nth($margin, 3);
}
.list-func-demo {
margin-bottom: 30px;
}
列表中除了可以包含简单的数字或字符串外,也可以包含其他列表。比如 1px 2px, 5px 6px
就是一个包含2个元素的列表,这2个元素又分别是列表 1px 2px
和列表 5px 6px
。
假设内外列表都是用的时空格或逗号时,可以使用小括号来区分开,比如 (1px 2px) (5px 6px)
。
需要了解的是,CSS 中并没有使用小括号区分列表的语法。所以 (1px 2px) (5px 6px)
装换成 CSS 的时候,会变成 1px 2px 5px 6px
。
下面的例子就是 Map:
$hello: (key1: value1, key2: value2, key3: value3);
与 list 不同的是,map 外面总是有小括号,并且其中的键值对总是用逗号隔开。其中的键和值都可以是任意 sass 对象。
与 list 相同的是,map 大部分时候也是用 sass 的map相关的函数来操作。
任何使用 list 的地方也可以使用 map。比如(key1: value1, key2: value2)
可以被当作是2层列表 key1 value1, key2 value2
。
Sass 支持标准的算术运算,加+
,减-
,乘*
,除/
和 模%
。 注意,Sass 在进行算术运算的时候会保留单位,所以你也不应该将不兼容的单位放在一起运算(比如把使用px
为单位的数字和使用em
为单位的数字作加法)。相同单位的两个数相乘也会出现平方单位(10px * 10px = 100px * px
),而px * px
并不是一个合法的 CSS 单位。
比较运算符<
, >
, <=
, >=
也可以用于 Sass 中的数字。 等于和不等于运算符 ==
, !=
则适用于 Sass 所有数据类型。
/
注意,因为在有些 CSS 属性中也会有符号/
,所以在 Sass 中除法运算符/
会有两种不同的作用。默认情况下,/
符号会当作字面字符串,而不是除法运算符。然而,有以下3种特殊情况,/
会被当做除法运算符。
p {
font: 10px/8px; // 不作除法
$width: 1000px;
width: $width/2; // 1 使用了变量,作除法
width: round(1.5)/2; // 1 使用了函数,作除法
height: (500px/2); // 2 使用了小括号,作除法
margin-left: 5px + 8px/2px; // 2 使用了 + ,作除法
font: (italic bold 10px/8px); // 2 在一个list中,不作除法
}
p {
font: 10px/8px;
width: 500px;
width: 1;
height: 250px;
margin-left: 9px;
font: italic bold 10px/8px;
}
-
符号 -
在 CSS 和 Sass 可能意味着减法符号(比如5px - 3px
),一个负数(比如-3px
),或者是一个属性名的一部分(比如font-weight
)。大部分时候,应该很容易区分其作用,但有时却会比较麻烦。以下是一些比较保险的规则:
-
符号两边要放置空格,比如 5px - 3px
-
符号前面要放置空格,而符号后面不要放空格 比如 -3px
, -$var
10px (-$var)
在解释 -
作何作用的时候,按以下顺序:
-
作为识别符(identifier)的一部分的时候,比如 a-1
会当作不带引号的字符串。唯一例外的是单位后面的 -
,比如 5px-3px
相当于 5px - 3px
,也就是减法。-
在2个数字之间,中间没有空格。会被当做减法,所以 1-2
相当于 1 - 2
-
在1个数字字面值前。会被当做负号。比如 1 -2
会被当做一个包含 1
和 -2
的 list-
在2个数字(包括数字变量)之间,无论是否有空格。也会被当做减法。比如 1 -$var
相当于 1 - $var
-
,会被当做负号所有的算术运算也都可以用于颜色值,只是要注意运算时是rgb分开进行计算的。比如下面的例子中,计算会被分成01 + 04 = 05
, 02 + 05 = 07
以及 03 + 06 = 09
:
p {
color: #010203 + #040506;
}
p {
color: #050709;
}
通常使用颜色函数(color functions)来进行颜色的操作。
颜色值 和 数字值 之间也是可以进行算术运算的,比如下面的例子中,计算会被分成01 * 2 = 02
, 02 * 2 = 04
以及 03 * 2 = 06
:
p {
color: #010203 * 2;
}
p {
color: #020406;
}
要注意,对于有 alpha 通道的颜色值,在算术运算时,2个操作数都必须是含有相同 alpha 值的颜色值。 并且运算时,不影响 alpha 值,比如:
p {
color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}
p {
color: rgba(255, 255, 0, 0.75);
}
如果要调整 alpha 通道值,可以使用 opacify
和 transparentize
函数。
加号 +
,可以用来连接字符串:
p {
cursor: e + -resize;
}
p {
cursor: e-resize;
}
对于 带引号字符串 和 不带引号字符串 之间的 +
运算的结果是否带引号,取决于 +
左边的值。
p:before {
content: "Foo " + Bar;
font-family: sans- + "serif";
}
p:before {
content: "Foo Bar";
font-family: sans-serif;
}
在字符串文本中,可以待插入的表达式或变量放到TODO中来进行插入:
p:before {
content: "I ate #{5 + 10} pies!";
}
p:before {
content: "I ate 15 pies!";
}
Null值在进行 字符串插入 时,会被当作 空字符串:
$value: null;
p:before {
content: "I ate #{$value} pies!";
}
p:before {
content: "I ate pies!";
}
对于布尔值,Sass中可以使用运算符 and
, or
以及 not
。
通常适用 list 函数来进行 list 的操作。
和其他语言一样,小括号可以用来预想运算的顺序:
p {
width: 1em + (2em * 3);
}
p {
width: 7em;
}
#{xxx}
property 和 selector 都可以使用#{xxx}
的方式来插入:
$name: foo;
$attr: border;
p.#{$name} {
#{$attr}-color: blue;
}
p.foo {
border-color: blue;
}
value 中也可以使用#{xxx}
插入。当然大部分时候我们都会直接使用变量,但使用#{xxx}
式插入,它旁边的运算符会被当做字面字符串,比如下面例子/
不会被当做除法符号:
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
}
p {
font: 12px/30px;
}
在进行变量赋值时,在值后加上 !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";
}
使用!default
时,值为null
的变量会被当做没有值。
$content: null;
$content: "Non-null content" !default;
#main {
content: $content;
}
#main {
content: "Non-null content";
}
@
规则 和 指令@import
Sass 扩展了 CSS 的 @import
功能,在 Sass 文件中可以 import 其他 SCSS 和 Sass 文件。被 import 的文件中的 变量 和 mixin 都可以在主文件中直接使用。
import Sass 文件时,@import
后面接文件名。但是如果是以下情况时,则当做 CSS 的@import
.css
,如 @import "foo.css"
http://
开头,如 @import "http://foo.com/bar";
url(xxx)
的方式, 如 @import url(foo);
@import
涉及到 media query,如 @import "foo" screen;
如果上面的条件不满足,文件扩展名是 .scss
或 .sass
时,该文件会被 import, 如果没有包含扩展名,则 Sass 会尝试查找使用该文件名,扩展名为 .scss
或 .sass
的文件,并 import 它。
例如,有文件 foo.scss
, 其中内容为:
a {
color: red;
}
则:
/* import 之前 */
@import "foo";
/* import 之后 */
/* import 之前 */
a {
color: red;
}
/* import 之后 */
@import "foo", "bar";
可以同时 import 文件 foo
和 bar
。
当一个目录中又多个 Sass 文件时,很多时候我们并不希望把所有这些文件都编译成一个单独的 CSS 文件,这时可以给不用编译成单独 CSS 文件的 Sass 文件的文件名前面加上下划线_
。在 import 这样的文件的时候,我们并不需要加上下划线。
比如你有个文件 _bar.scss
,因为有文件名以下划线开头,所以不会生成_bar.css
文件。但你可以在你的主 sass 文件中,import 该文件。
@import "bar";
/* in _bar.scss */
a {
color: green;
}
@import
我们可以在 CSS rule 或 @media
rule 中进行@import
。 要注意的是,CSS selector 也会嵌套。
比如文件 _baz.scss
中包含如下内容:
.example {
color: red;
}
则:
#main {
@import "baz";
}
#main .example {
color: red;
}
@media
Sass 中的 @media
的功能和 CSS 中的类似,但在 Sass 中 @media
可以被嵌套在 CSS rule中。如果 @media
嵌套在 CSS rule 中,则作用时它会自动冒泡到顶层。比如:
.sidebar {
width: 300px;
@media screen and (orientation: landscape) {
width: 500px;
}
}
.sidebar {
width: 300px;
}
@media screen and (orientation: landscape) {
.sidebar {
width: 500px;
}
}
@media
queries 之间也可以进行相互嵌套。这时 queries 之间使用 and
进行合并。如:
@media screen {
.sidebar {
@media (orientation: landscape) {
width: 500px;
}
}
}
@media screen and (orientation: landscape) {
.sidebar {
width: 500px;
}
}
@midia
queries 中也可以在 feature names 和 feature values 的地方使用 sass 表达式,包括变量,函数,运算操作符。比如:
$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;
}
}
@extend
@extend
指令可以用来继承另一个 selector 的样式。比如:
.a {
border: 1px #f00;
}
.b {
@extend .a;
border-width: 3px;
}
.a, .b {
border: 1px #f00;
}
.b {
border-width: 3px;
}
从上面的例子中可以看出来,实际上 Sass 就是在 .a
处插入 .b
。
实际上,其他包含了 .a
的 rule,也会被 .b
所使用。比如:
.error {
border: 1px #f00;
}
.error.minor {
background-color: #eee;
}
.critial {
@extend .error;
color: tomato;
}
.error, .critial {
border: 1px #f00;
}
.error.minor, .minor.critial {
background-color: #eee;
}
.critial {
color: tomato;
}
@extend
不仅适用于 class selector,对于其他 selector 也适用,比如 .special.cool
, a:hover
, a.user[href^="http://"]
等。比如
.hoverlink {
@extend a:hover;
}
a:hover {
text-decoration: underline;
}
a:hover, .hoverlink {
text-decoration: underline;
}
和前面error.minor
的例子一样, 其他任何包含 a:hover
的规则也会被用于 hoverlink
, 及时其中包含其他 selector。 比如:
.hoverlink {
@extend a:hover;
}
.comment a.user:hover {
font-weight: bold;
}
.comment a.user:hover, .comment .user.hoverlink {
font-weight: bold;
}
@extend
的 selector使用 %
可以定义一个只用于 extened 的 selector,它相当于占位(placeholder) selector。这样的 selector 及其 rule 不会直接生成到 CSS 中。在定义时,相当于把符号 %
用到可以用在符号 #
和符号 .
的位置。比如:
/* before */
#context a%extreme {
color: blue;
}
/* after */
/* before */
/* after */
然后我们可以 @extend
这样一个占位 selector。比如:
.outer %inner {
color: red;
}
.content {
@extend %inner;
}
.outer .content {
color: red;
}
@at-root
@at-root
可以让原本嵌套在其他 selector 中的 selector 置于顶层。比如:
.parent {
color: red;
@at-root {
.child1 { font-size: 16px; }
.child2 { border-width: 2px; }
}
.step-child { background-color: #ccc; }
}
.parent {
color: red;
}
.child1 {
font-size: 16px;
}
.child2 {
border-width: 2px;
}
.parent .step-child {
background-color: #ccc;
}
@debug
@debug
可以将 Sass 表达式的值打印到标准错误。可以方便的进行 debug。比如:
@debug 10em + 12em;
会在终端输出:
Line 1 DEBUG: 22em
@warn
@warn
也可以将 Sass表达式的值打印到标准错误。@warn
和 @debug
的区别在于,@warn
在 CLI 选项 --quiet
或 Sass 选项 :quiet
进行关闭,另外 @warn
中打印的消息也会包含 warning 的地方。
例子:
@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;
}
@error
@error
用来抛出一个错误,其中也会伴随相应的 stack trace。很适合用来对 mixins 和 函数 中的参数进行合法性验证。比如:
@mixin adjust-location($x, $y) {
@if unitless($x) {
@error "$x may not be unitless, was #{$x}.";
}
@if unitless($y) {
@error "$y may not be unitless, was #{$y}.";
}
position: relative; left: $x; top: $y;
}
if()
if()
是 Sass 中的内置函数。
下面的例子中,第一表达式回返回1px
, 而第二个会返回 2px
。
if(true, 1px, 2px)
if(false, 1px, 2px)
@if
@if
指令使用一个 sass 表达式作为参数。如果该表达式的返回 false
或 null
以外的值,则该指令中嵌套的 style 会被使用。比如:
p.with-border {
@if 1 + 1 == 2 { border: 1px solid; }
@if 5 < 3 { border: 2px dotted; }
@if null { border: 3px double; }
}
p.with-border {
border: 1px solid;
}
@if
指令后面可以再接多个 @else if
语句,或者一个 @else
语句。比如:
$type: monster;
p.colorful {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
p.colorful {
color: green;
}
@for
@for
指令用于构建循环语句。
语法:
@for $var from <start> through <end>
@for $var from <start> to <end>
其中 $var
被称为 counter,当然你也可以写成 $i
或 $j
。 而 <start>
和 <end>
都必须是可以返回整数的 Sass 表达式。 如果 <start>
比 <end>
大,则 $var
会进行递减而不是递增。
使用第1种语法,使用 through
,则循环的时候 $var
的值会从 <start>
每次加1一直到 <end>
(包含<end>
),。而使用第2种语法,使用 to
,循环时 $var
也是从 <start>
逐次加1直到 <end>
,但不会包含 <end>
本身。
@for $i from 1 through 3 {
.item-#{$i} { width: 2em * $i; }
}
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}
@each
@each
指令也用于构建循环语句。
语法:
@each $var in <list or map>
其中 <list or map>
必须是 list 或者 map 或者是可以返回 list 或 map 的 Sass 表达式。
在循环的过程中 $var
的值会被设为 list 或 map 中的各项。
例子:
@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");
}
@each
也可以使用多个 counter。
语法:
@each $var1, $var2, ... in <list>
其中 <list>
是一个包含多个列表的列表。
例如:
@each $animal, $color, $cursor in (puma, black, default),
(sea-slug, blue, pointer),
(egret, white, move) {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
.puma-icon {
background-image: url("/images/puma.png");
border: 2px solid black;
cursor: default;
}
.sea-slug-icon {
background-image: url("/images/sea-slug.png");
border: 2px solid blue;
cursor: pointer;
}
.egret-icon {
background-image: url("/images/egret.png");
border: 2px solid white;
cursor: move;
}
使用 map 的话是这样的。
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
#{$header} {
font-size: $size;
}
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
@while
循环用法:
@while <expression> {
...
}
@while
循环会一直到表达式 <expression>
的值为 false
时才停止。
$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;
}
@mixin
mixin 可以用来定义可重用的 CSS style。 mixin 可以接收参数,这可以让我们获得更灵活的 style。
指令 @mixin
可以定义一个 mixin,指令 @include
可以用来使用一个 mixin。
下面的例子定义并使用了一个叫 large-text
的 mixin:
/* 定义 mixin */
@mixin large-text {
font: {
family: Arial;
size: 20px;
weight: bold;
}
color: #ff0000;
}
/* 使用 mixin */
.page-title {
@include large-text;
padding: 4px;
margin-top: 10px;
}
/* 定义 mixin */
/* 使用 mixin */
.page-title {
font-family: Arial;
font-size: 20px;
font-weight: bold;
color: #ff0000;
padding: 4px;
margin-top: 10px;
}
在 mixin 中,也可以包含 selector,也可以使用 &
符号来引用父级 selector。
比如:
@mixin clearfix {
display: inline-block;
&:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html & { height: 1px }
}
mixin 也可以直接用在顶层(不在任何 selector rule 中)。比如:
@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; }
h2.highlight {
@include compound;
}
h2.highlight {
background-color: #fc0;
font-size: 20px;
}
例子:
@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 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 的时候,我们也可以把传入的参数写成 键值对 的形式。这样可以让代码明确已读,而且使用的时候也不用在意传参的顺序。
p {
@include sexy-border($color: blue);
}
h1 {
@include sexy-border( $width: 2in, $color: blue);
}
p {
border-color: blue;
border-width: 1in;
border-style: dashed;
}
h1 {
border-color: blue;
border-width: 2in;
border-style: dashed;
}
有时我们希望使用非固定数量的参数 mixin。 比如 box-shadow
可以接受多个 shadow 样式作为参数, 对于这种情况就要使用 不定参数 的 mixin。 在定义这种 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 的时候,也可以使用不定参数。
其实就是对 list 和 map 进行展开。下面例子分别展示了使用 list 和 map :
@mixin colors($text, $background, $border) {
color: $text;
background-color: $background;
border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
@include colors($values...);
}
$value-map: (text: #00ff00, background: #0000ff, border: #ff0000);
.secondary {
@include colors($value-map...);
}
.primary {
color: #ff0000;
background-color: #00ff00;
border-color: #0000ff;
}
.secondary {
color: #00ff00;
background-color: #0000ff;
border-color: #ff0000;
}
你也可以同时 list 和 map 展开,只要你在调用的时候,把 list 放在 map 前面。
你可以使用 不定参数 重新封装一个 mixin,这样你可以在不改变这个原 mixin 的情况下,添加额外的 style。 比如:
@mixin stylish-mixin($color, $width) {
color: $color;
width: $width;
}
@mixin wrapped-stylish-mixin($args...) {
font-weight: bold;
@include stylish-mixin($args...);
}
.stylish {
// 参数 $witdh 会被作为关键字参数传给 "stylish-mixin"
@include wrapped-stylish-mixin(#00ff00, $width: 100px);
}
.stylish {
font-weight: bold;
color: #00ff00;
width: 100px;
}
在 mixin 定义中,可以使用指令 @content
来获取这个 block 的内容。在一个 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);
}
要注意,传给 mixin 的 block 会使用它定义时的作用域,而不是 mixin 的内部作用域。下面的例子中,@content
在转换的时候,变量 $color
和 size
并不会使用 mixin 自己 local 的 $color
和 size
变量,而是原 block 定义时所在作用域的相应变量。
$color: white;
@mixin colors($color: blue, $size: 200px) {
background-color: $color;
@content;
border-color: $color;
width: $size;
}
.colors {
$size: 1em;
@include colors {
color: $color;
font-size: $size;
}
}
.colors {
background-color: blue;
color: white;
font-size: 1em;
border-color: blue;
width: 200px;
}
@function
指令用来定义个 function,在 function 定义中使用 @return
指令来返回一个值。
在调用 function 时,并不需要 @include
指令。而且也可以使用关键字参数。
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
#sidebar { width: grid-width(5); }
#sidebar_2 { width: grid-width($n: 10); }
#sidebar {
width: 240px;
}
#sidebar_2 {
width: 490px;
}
Sass 中定义了一些有用的函数,完整的函数列表在这。
比如这里调用操作颜色的函数 hsl()
:
p {
color: hsl(0, 100%, 50%);
}
p {
color: red;
}
Sass 在调用时可以使用关键词参数,使用关键词参数可以提高易读性。同时也不用在意参数顺序。比如上面的例子可以写成:
p {
color: hsl($hue: 0, $lightness: 50%, $saturation: 100%);
}
p {
color: red;
}