参考文献:

Sass 中文网

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 部分文件

当通过 @importsass 样式分散到多个文件时,你通常只想生成少数几个 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 .bazcss 规则。当这条规则应用到 .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),看起来很像普通的 idclass 选择器,只是 #. 被替换成了 %。可以像 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>,区别在于 throughto 的含义:当使用 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'); }