参考文献:
1. 变量
声明变量
$highlight-color: #F90;
$basic-border: 1px solid black;
变量是有作用域的
$nav-color: #F90;
nav {
$width: 100px;
width: $width;
color: $nav-color;
}
变量是会被覆盖的
$link-color: blue;
$link-color: red;
a {
color: $link-color;
}
2. 嵌套
#content {
article {
h1 { color: #333 }
p { margin-bottom: 1.4em }
}
aside { background-color: #EEE }
}
父元素选择器 &
article a {
color: blue;
&:hover { color: red }
}
嵌套属性
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
// border 称之为命名空间,命名空间也可以有自己的属性值
.funky {
font: 20px/24px {
family: fantasy;
weight: bold;
}
}
// 编译为
.funky {
font: 20px/24px;
font-family: fantasy;
font-weight: bold;
}
3. 导入 SASS 文件
导入 sass 文件,无需在后面加 .scss
3.1 SASS 部分文件
当通过 @import
把 sass
样式分散到多个文件时,你通常只想生成少数几个 css
文件。那些专门为 @import
命令而编写的 sass
文件,并不需要生成对应的独立 css
文件,这样的 sass
文件称为局部文件。对此,sass
有一个特殊的约定来命名这些文件。
此约定即,sass
局部文件的文件名以下划线开头。这样,sass
就不会在编译时单独编译这个文件输出 css
,而只把这个文件用作导入。当你 @import
一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。举例来说,你想导入 themes/_night-sky.scss
这个局部文件里的变量,你只需在样式表中写 @import
"themes/night-sky";
。
局部文件可以被多个不同的文件引用。当一些样式需要在多个页面甚至多个项目中使用时,这非常有用。在这种情况下,有时需要在你的样式表中对导入的样式稍作修改,sass
有一个功能刚好可以解决这个问题,即默认变量值。
3.2 默认变量值
重复声明变量会被覆盖。
!default
可以声明默认值。如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。
$fancybox-width: 400px !default;
.fancybox {
width: $fancybox-width;
}
3.3 嵌套导入
// 局部文件 _blue-theme.scss
aside {
background: blue;
color: white;
}
// 别的文件
.blue-theme {@import "blue-theme"}
// 生成的结果跟你直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样。
.blue-theme {
aside {
background: blue;
color: #fff;
}
}
4. 注释
body {
color: #333; // 这种注释内容不会出现在生成的css文件中
padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}
5. 混合器
5.1 混合器基本使用
混合器使用 @mixin
标识符定义。
@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;
}
最终生成
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
混合器中不仅可以包含属性,也可以包含 css
规则,包含选择器和选择器中的属性
@mixin no-bullets {
list-style: none;
li {
list-style-image: none;
list-style-type: none;
margin-left: 0px;
}
}
5.2 给混合器传参
@mixin link-colors($normal, $hover, $visited) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
a {
@include link-colors(blue, red, green);
}
//Sass最终生成的是:
a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }
也可以通过这种方式传递参数,不需要在意顺序
a {
@include link-colors(
$normal: blue,
$visited: green,
$hover: red
);
}
5.3 默认参数值
为了在 @include
混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用 $name: default-value
的声明形式,默认值可以是任何有效的 css
属性值,甚至是其他参数的引用。
@mixin link-colors(
$normal,
$hover: $normal,
$visited: $normal
)
{
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
// 调用
@include link-colors(red)
6. 继承
使用 sass
的时候,最后一个减少重复的主要特性就是选择器继承。这个通过@extend
语法实现,如下代码:
//通过选择器继承继承样式
.error {
border: 1px solid red;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
在上边的代码中,.seriousError
将会继承样式表中任何位置处为 .error
定义的所有样式。以 class="seriousError"
修饰的 html
元素最终的展示效果就好像是 class="seriousError error"
。相关元素不仅会拥有一个 3px
宽的边框,而且这个边框将变成红色的,这个元素同时还会有一个浅红色的背景,因为这些都是在 .error
里边定义的样式。
.seriousError
不仅会继承 .error
自身的所有样式,任何跟 .error
有关的组合选择器样式也会被 .seriousError
以组合选择器的形式继承,如下代码:
//.seriousError从.error继承样式
.error a{ //应用到.seriousError a
color: red;
font-weight: 100;
}
h1.error { //应用到hl.seriousError
font-size: 1.2rem;
}
- 跟混合器相比,继承生成的
css
代码相对更少。因为继承仅仅是重复选择器,而不会重复属性,所以使用继承往往比混合器生成的css
体积更小。如果你非常关心你站点的速度,请牢记这一点。 - 继承遵从
css
层叠的规则。当两个不同的css
规则应用到同一个html
元素上时,并且这两个不同的css
规则对同一属性的修饰存在不同的值,css
层叠规则会决定应用哪个样式。相当直观:通常权重更高的选择器胜出,如果权重相同,定义在后边的规则胜出。
注意事项
.foo .bar { @extend .baz; }
.bip .baz { a: b; }
在上边的例子中,sass
必须保证应用到 .baz
的样式同时也要应用到 .foo .bar
。例子中有一条应用到 .bip .baz
的 css
规则。当这条规则应用到 .foo .bar
时,可能存在三种情况,如下代码:
<!-- 继承可能迅速变复杂 -->
<!-- Case 1 -->
<div class="foo">
<div class="bip">
<div class="bar">...</div>
</div>
</div>
<!-- Case 2 -->
<div class="bip">
<div class="foo">
<div class="bar">...</div>
</div>
</div>
<!-- Case 3 -->
<div class="foo bip">
<div class="bar">...</div>
</div>
为了应付这些情况,sass
必须生成三种选择器组合(仅仅是 .bip .foo .bar
不能覆盖所有情况)。如果任何一条规则里边的后代选择器再长一点,sass
需要考虑的情况就会更多。实际上 sass
并不总是会生成所有可能的选择器组合,即使是这样,选择器的个数依然可能会变得相当大,所以如果允许,尽可能避免这种用法。
值得一提的是,只要你想,你完全可以放心地继承有后代选择器修饰规则的选择器,不管后代选择器多长,但有一个前提就是,不要用后代选择器去继承。
7. 运算
SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %
),如果必要会在不同单位间转换值。
关系运算 <, >, <=, >=
也可用于数字运算,相等运算 ==, !=
可用于所有数据类型。
除法运算
以下三种情况 /
将被视为除法运算符号:
- 如果值,或值的一部分,是变量或者函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
p {
font: 10px/8px; // Plain CSS, no division
$width: 1000px;
width: $width/2; // Uses a variable, does division
width: round(1.5)/2; // Uses a function, does division
height: (500px/2); // Uses parentheses, does division
margin-left: 5px + 8px/2px; // Uses +, does division
}
编译为
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
如果需要使用变量,同时又要确保 /
不做除法运算而是完整地编译到 CSS 文件中,只需要用 #{}
插值语句将变量包裹。
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
}
// 编译为
p {
font: 12px/30px;
}
插值语句
通过 #{}
插值语句可以在选择器或属性名中使用变量:
$name: foo;
$attr: border;
p.#{$name} {
#{$attr}-color: blue;
}
// 编译为
p.foo {
border-color: blue;
}
#{}
插值语句也可以在属性值中插入 SassScript,大多数情况下,这样可能还不如使用变量方便,但是使用 #{}
可以避免 Sass 运行运算表达式,直接编译 CSS。
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
}
// 编译为
p {
font: 12px/30px;
}
8. @指令
8.1 @media
Sass 中 @media
指令与 CSS 中用法一样,只是增加了一点额外的功能:允许其在 CSS 规则中嵌套。如果 @media
嵌套在 CSS 规则内,编译时,@media
将被编译到文件的最外层,包含嵌套的父选择器。这个功能让 @media
用起来更方便,不需要重复使用选择器,也不会打乱 CSS 的书写流程。
.sidebar {
width: 300px;
@media screen and (orientation: landscape) {
width: 500px;
}
}
// 编译为
.sidebar {
width: 300px;
}
@media screen and (orientation: landscape) {
.sidebar {
width: 500px;
}
}
@media
的 queries 允许互相嵌套使用,编译时,Sass 自动添加 and
@media screen {
.sidebar {
@media (orientation: landscape) {
width: 500px;
}
}
}
// 编译为
@media screen and (orientation: landscape) {
.sidebar {
width: 500px;
}
}
8.2 @extend-Only 选择器
有时,需要定义一套样式并不是给某个元素用,而是只通过 @extend
指令使用,尤其是在制作 Sass 样式库的时候,希望 Sass 能够忽略用不到的样式。
如果使用普通的 CSS 规则,最后会编译出很多用不到的样式,也容易与其他样式名冲突,所以,Sass 引入了“占位符选择器” (placeholder selectors),看起来很像普通的 id
或 class
选择器,只是 #
或 .
被替换成了 %
。可以像 class 或者 id 选择器那样使用,当它们单独使用时,不会被编译到 CSS 文件中。
#context a%extreme {
color: blue;
font-weight: bold;
font-size: 2em;
}
.notice {
@extend %extreme;
}
// 编译为
#context a.notice {
color: blue;
font-weight: bold;
font-size: 2em;
}
8.3 @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.4 @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'); }