5、混合器 @mixin
5.1、混合器的使用规则
如果有一些重复样式,那么使用变量来统一处理这种情况非常不错的选择。但当样式变得越来越复杂,需要大段的重复样式代码,独立的变量就没办法应付这种情况了。所有可以通过sass
的混合器实现大段样式的重用。
@mixin rounded-corners {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
上面定义了一个混合器,那么引入它就需要用到 @include
, 例子:
.notice {
background-color: green;
border: 2px solid #00aa00;
@include rounded-corners;
}
最终生成的 css
样式如下:
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
为便于书写,@mixin
可以用 =
表示,而 @include
可以用 +
表示
混合器传参
混合器并不一定总得生成相同的样式。可以通过在 @include
混合器时给混合器传参,来定制混合器生成的精确样式。
@mixin link-colors($normal, $hover, $visited) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
当混合器被 @include
时,你可以把它当作一个css函数来传参。如果你像下边这样写:
a {
@include link-colors(blue, red, green);
}
css
最终生成的是:
a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }
5.3、默认参数值
为了在 @include
混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用 $name: default-value
的声明形式,默认值可以是任何有效的 css
属性值,甚至是其他参数的引用,如下代码:
@mixin link-colors($normal, $hover: $normal, $visited: $normal) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
使用:
a {
@include link-colors(red);
}
css
最终生成的是:
a { color: red; }
a:hover { color: red; }
a:visited { color: red; }
6、选择器继承
使用 sass
的时候,最后一个减少重复的主要特性就是选择器继承。选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。这个通过 @extend
语法实现,如下代码:
.error {
border: 1px solid red;
background-color: #fdd;
}
.seriousError {
@extend .error; // 继承 error 样式
border-width: 3px;
}
.seriousError
不仅会继承.error自身的所有样式,任何跟 .error
有关的组合选择器样式也会被 .seriousError
以组合选择器的形式继承,如下代码:
.error a{ //应用到.seriousError a
color: red;
font-weight: 100;
}
h1.error { //应用到hl.seriousError
font-size: 1.2rem;
}
就是相当于多了一个类名:
<div class="seriousError error"></div>
7、嵌套 @import
大多数情况下,一般在文件的最外层(不在嵌套规则内)使用 @import
,其实,也可以将 @import
嵌套进 CSS
样式或者 @media
中,与平时的用法效果相同,只是这样导入的样式只能出现在嵌套的层中。
假设 example.scss 文件包含以下样式:
.example {
color: red;
}
然后导入到 #main
样式内:
#main {
@import "example";
}
这将会被编译为:
#main .example {
color: red;
}
8、SassScript
8.1、变量
$w: 10px;
直接使用变量:
.main {
width: $w;
}
8.2、运算
所有数据类型均支持相等运算 ==
或 !=
,此外,每种数据类型也有其各自支持的运算方式。
p {
width: 1pin + 8pt;
}
编译为:
p {
width: 1.111in;
}
关系运算 <
, >
, <=
, >=
也可用于数字运算,相等运算 ==
, !=
可用于所有数据类型。
以下三种情况 / 将被视为除法运算符号:
- 如果值,或值的一部分,是变量或者函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
p {
font: 10px/8px;
$width: 1000px;
width: $w/2;
width: round(1.5)/2;
height: (500px/2);
margin-left: 5px + 8px/2px;
}
编译为:
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
8.3、颜色值运算
颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值:
p {
color: #010203 + #040506;
background: #010203 * 2; // 生成: #020406
}
颜色值的 alpha channel
可以通过 opacify 或 transparentize 两个函数进行调整。
$translucent-red: rgba(255, 0, 0, 0.5);
p {
color: opacify($translucent-red, 0.3);
background-color: transparentize($translucent-red, 0.25);
}
8.4、函数
SassScript
定义了多种函数,有些甚至可以通过普通的 CSS
语句调用:
p {
color: hsl(0, 100%, 50%);
}
Sass
函数允许使用关键词参数,上面的例子也可以写成:
p {
color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);
}
8.5、插值语句
通过 #{}
插值语句可以在选择器或属性名中使用变量:
$name: foo;
$attr: border;
p.#{$name} {
#{$attr}-color: blue;
}
编译为:
p.foo {
border-color: blue;
}
8.6、判断语句
@mixin does-parent-exist {
@if & {
&:hover {
color: red;
}
} @else {
a {
color: red;
}
}
}
当 @if
的表达式返回值不是 false
或者 null
时,条件成立,输出 {} 内的代码:
.p1 {
@if 1 + 1 == 2 { border: 1px solid; }
@if 5 < 3 { border: 2px dotted; }
@if null { border: 3px double; }
}
$type: matador;
.p2 {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
编译为:
.p1 {
border: 1px solid;
}
.p2 {
color: red;
}
8.7、@for
@for
指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。这个指令包含两种格式:
@for $var from <start> through <end>
@for $var from <start> to <end>
区别在于 through
与 to
的含义:当使用 through
时,条件范围包含 <start>
与 <end>
的值,而使用 to
时条件范围只包含 <start>
的值不包含 <end>
的值。另外,$var
可以是任何变量,比如 $i
;<start>
和 <end>
必须是整数值。
@for $i from 1 through 3 {
.item-#{$i} { width: 2em * $i; }
}
编译为:
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}
8.8、@each
@each
指令的格式是 $var in <list>
, $var
可以是任何变量名,比如 $length
或者 $name
,而 <list>
是一连串的值,也就是值列表。
@each
将变量 $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');
}
8.9、@while
@while
指令重复输出格式直到表达式返回结果为 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;
}
分音 (Partials)
如果需要导入 SCSS
或者 Sass
文件,但又不希望将其编译为 CSS
,只需要在文件名前添加下划线,这样会告诉 Sass
不要编译这些文件,但导入语句中却不需要添加下划线。
例如,将文件命名为 _colors.scss
,便不会编译 _colours.css
文件。
@import "colors";
上面的例子,导入的其实是 _colors.scss
文件
注意,不可以同时存在添加下划线与未添加下划线的同名文件,添加下划线的文件将会被忽略。