Sass用法

什么是Sass

Sass 是对 CSS 的扩展,是一种CSS预处理器,让 CSS 语言更强大、优雅。 它允许你使用变量、嵌套规则、 mixins、导入等众多功能, 并且完全兼容 CSS 语法看, 使得CSS的开发,变得简单和可维护。

Sass安装

在Ruby环境下执行

gem install sass

编译(使用)

单文件转换

sass style.scss style.css

单文件监听命令

sass --watch style.scss:style.css

文件夹监听命令

sass --watch sassDir:cssDir

css 文件转换成scss/sass文件

sass-convert style.css style.sass
sass-convert style.css style.scss

我们一般常用的有--style,--sourcemap,--debug-info等。

sass --watch style.scss:style.css --style compact
sass --watch style.scss:style.css --sourcemap
sass --watch style.scss:style.css --style expanded --sourcemap
sass --watch style.scss:style.css --debug-info
  • style表示解析后的css是什么格式,有四种取值分别为:nested,expanded,compact,compressed。
  • sourcemap表示开启sourcemap调试。开启sourcemap调试后,会生成一个后缀名为.css.map文件。
  • debug-info表示开启debug信息,升级到3.3.0之后因为sourcemap更高级,这个debug-info就不太用了。

四种style生成后的css

// nested
#main {
  color: #fff;
  background-color: #000; }
  #main p {
    width: 10em; }

.huge {
  font-size: 10em;
  font-weight: bold;
  text-decoration: underline; }

// expanded
#main {
  color: #fff;
  background-color: #000;
}
#main p {
  width: 10em;
}

.huge {
  font-size: 10em;
  font-weight: bold;
  text-decoration: underline;
}

// compact
#main { color: #fff; background-color: #000; }
#main p { width: 10em; }

.huge { font-size: 10em; font-weight: bold; text-decoration: underline; }

// compressed
#main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}

基本使用

注释

SASS共有两种注释风格。
标准的CSS注释 /* comment */,会保留到编译后的文件。
单行注释 // comment,只保留在SASS源文件中,编译后被省略。
在/*后面加一个感叹号,表示这是"重要注释"。即使是压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。

/*! 
 重要注释!
*/

嵌套规则(Nested Rules)

SASS允许选择器嵌套,比如下面代码

#a {
    .a-1{
        background:yellow;
        .child{
            font-size:12px;
            .child-1{
                color:red
            }
        }
    }
}

编译后的结果:

#a .a-1 {
  background: yellow;
}

#a .a-1 .child {
  font-size: 12px;
}

#a .a-1 .child .child-1 {
  color: red;
}

引用父选择符: & ==> parent selector

& 在编译时将被替换为父选择符,输出到 CSS 中,多用于伪类,如 a:hover , a:active , a:visited , a:first-letter , a:last-child等,比如下面代码:

.hello {
    .dropdown{
        display: none;
    }
  &:hover {
        .dropdown{
            display: block;
        }
    }
}

编译后的结果:

.hello .dropdown {
 display: none;
}

.hello:hover .dropdown {
 display: block;
}

属性嵌套

主要用于复合属性,比如background、font等

.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
  border: {
    radius:20px;
    color:red;
  }
}

编译后的结果:

.funky {
  font-family: fantasy;
  font-size: 30em;
  font-weight: bold;
  border-radius: 20px;
  border-color: red;
}

变量(Variables)

SASS允许使用变量,所有变量以$开头。写法就像CSS一样

$width: 10px;
#main {
  width: $width;
}

作用域

变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明:

$width: 10px;
.p {
  $width: 30px;
  .a{
    width: $width
  }
}

编译结果为:

.p .a {
  width: 30px; 
}

插值(Interpolation)

如果变量需要镶嵌在字符串之中,就必须需要写在#{}(插值Interpolation)之中,比如:

$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
  content: "hello world #{$name}"
}

运算

Sass支持数字的标准运算(加 +、减 -、乘 *、除 /和取模 %)

p {
  width: (1em + 2em) * 3;    
}

//也可以写成这样
p {
  width: (1 + 2em) * 3;    
}

//或者这样
p {
  width: (1em + 2) * 3;    
}

编译后的结果:

p {width: 9em;}
除法运算

在以下三种情况中,/ 会被解释为除法运算。 这已经覆盖了绝大多数真正使用除法运算的情况:

  1. 如果数值或它的任意部分是存储在一个变量中或是函数的返回值。
  2. 如果数值被圆括号包围。
  3. 如果数值是另一个数学表达式的一部分
p {
  font: 10px/8px;           // 纯 CSS,不是除法运算
  $width: 1000px;
  width: $width/2;            // 使用了变量,是除法运算
  width: round(1.5)/2;        // 使用了函数,是除法运算
  height: (500px/2);          // 使用了圆括号,是除法运算
  margin-left: 5px + 8px/2px; // 使用了加(+)号,是除法运算
}

编译后的结果:

p {
  font: 10px/8px;     //没有进行编译
  width: 500px;
  width: 1;
  height: 250px;
  margin-left: 9px;
}

如果你希望在编译后的 CSS 中使用变量和 /, 你可以用 #{} 包住变量。 例如:

p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};
}

编译后的结果:

p {
  font: 12px/30px;
}
颜色运算
p {
  color: #123123 + #040506;
}

编译后的结果:

p {
  color: #163629;
}

在文本字符串中,#{} 形式的表达式可以被用来在字符串中添加动态值:
空值会被视作空字符串:

p:before {
  content: "I ate #{5 + 10} pies!";
}
$value: null;
p:before {
  content: "I ate #{$value} pies!";
}

编译后的结果:

p:before {
  content: "I ate 15 pies!";
}

p:before {
  content: "I ate  pies!";
}

规则和指令(directive )

(导入)@import

Sass 扩展了 CSS 的 @import 规则,让它能够引入 scss 和sass 文件,Sass的@import规则和CSS的有所不同,编译时会将@import的scss文件合并进来只生成一个CSS文件。但是如果你在Sass文件中导入css文件如@import 'reset.css',那效果跟普通CSS导入样式文件一样,导入的css文件不会合并到编译后的文件中,而是以@import方式存在。
用法如下:

@import "basic.scss";  

还可以嵌套使用,相当于个编译后的basic .css加了一个命名空间,

.example {
  @import "basic.scss";
}

编译后的结果:

.example #a .a-1 {
  background: yellow;
}

.example #a .a-1 .child {
  font-size: 12px;
}

.example #a .a-1 .child .child-1 {
  color: red;
}
媒体查询(@media)

Sass 中 @media 指令与 CSS 中用法一样,只是增加了一点额外的功能:允许其在 CSS 规则中嵌套。如果 @media 嵌套在 CSS 规则内,编译时,@media 将被编译到文件的最外层,包含嵌套的父选择器。这个功能让 @media 用起来更方便,不需要重复使用选择器,也不会打乱 CSS 的书写流程。

.father{
    .sidebar {
          width: 300px;
          @media screen and (orientation: landscape) {
             width: 500px;
            .hello{
                font-size:20px
            }
          }
    }
}

编译后的结果:

.father .sidebar {
  width: 300px;
}

@media screen and (orientation: landscape) {
  .father .sidebar {
    width: 500px;
  }
  .father .sidebar .hello {
    font-size: 20px;
  }
}
继承(@extend)
  • 简单继承

Sass中,选择器继承可以让选择器继承另一个选择器的所有样式,并联合声明。使用选择器的继承,要使用关键词@extend,后面紧跟需要继承的选择器。
比如:

.error {
  border: 1px #f00;
  &.intrusion {
      background-image: url("/image/hacked.png");
    }
}
.seriousError {
  @extend .error;
}

编译后的结果:

.error, .seriousError, {
  border: 1px #f00;
}

.error.intrusion {
  background-image: url("/image/hacked.png");
}
  • 多元素继承(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;
}
  • 链式继承(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%;
}

从编译后的CSS中不难看出,类名“.error”变成了群组选择,添加了类名“.seriousError”和类名“.criticalError”。而类名“.seriousError”变成了群组选择,添加了类名“.criticalError”。这就叫做链式继承。

混合(@mixin)

Sass中使用@mixin声明混合,可以传递参数,参数名以$符号开始,多个参数以逗号分开,也可以给参数设置默认值。声明的@mixin通过@include来调用。

  • 使用

通过@mixin定义混合

@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

通过@include调用定义的混合

 .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 sexy-border($color:blue, $width:20px) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
//不传参,使用默认参数
p { @include sexy-border;}

//传参数
p { @include sexy-border(green, 10px); }
```

```
//不传参,使用默认参数
p {
  border-color: blue;
  border-width: 20px;
  border-style: dashed;
}

//传参数
p {
  border-color: green;
  border-width: 10px;
  border-style: dashed;
}
```
- 多组值参数mixin

如果一个参数可以有多组值,如box-shadow、transition等,那么参数则需要在变量后加三个点表示,如$shadow...,比如:
```
@mixin box-shadow($shadow...) {
  -webkit-box-shadow:$shadow;
  box-shadow:$shadow;
}
.box{
  border:1px solid #ccc;
  @include box-shadow(0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3));
}
```
编译后的结果:
```
.box{
  border:1px solid #ccc;
  -webkit-box-shadow:0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3);
  box-shadow:0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3);
}
```
#### 条件指令
###### @if: @if可一个条件单独使用,也可以和@else或者@else if 结合多条件使用
```
p {
  @if 1 + 1 == 2 { border: 1px solid;  }
  @if true {background-image:url('')}
  @if 5 < 3      { border: 2px dotted; }
  @if null       { border: 3px double; }
}

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
```
编译后的结果:
```
p {
  border: 1px solid;
  background-image: url("");
}

p {
  color: green;
}
```
#### 循环指令
###### @for 
for循环有两种形式,分别为:@for $var from  through 和@for $var from  to 。$i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。
```
/*from ... through*/
@for $i from 1 through 3 { //1,2,3
  .item-#{$i} { width: 2em * $i; }
}

###

/*from ... to*/
@for $i from 1 to 3 {  //1,2
  .item-to-#{$i} { width: 2em * $i; }
}
```
编译后的结果:
```
/*from ... through*/
.item-1 {
  width: 2em;
}
.item-2 {
  width: 4em;
}
.item-3 {
  width: 6em;
}


/*from ... to*/
.item-to-1 {
  width: 2em;
}
.item-to-2 {
  width: 4em;
}
```

###### @each
语法为:@each $var in 。其中$var表示变量。
```
//单字段
@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}


//多字段
$animal-data: (puma, black, default),(sea-slug, blue, pointer),(egret, white, move);
@each $animal, $color, $cursor in $animal-data {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
    border: 2px solid $color;
    cursor: $cursor;
  }
}
```
编译结果为:
```
//单字段
.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");
}


//多字段
.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; 
}
```
###### @while
@while和@for指令很相似,只要@while后面的条件为true就会执行。

```
$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;
}
```

### 自定义函数
```
$grid-width: 40px;
$gutter-width: 10px;

@function test($a){
    @return $a+10
}

@function grid-width($n) {
    $hello:1px ;
    @for $i from 1 through $n{
        $hello:$hello+$i
    }
    @if $hello > 10 {
        $hello:15px
    }
    @return $hello + test(2)
}

#sidebar { width: grid-width(5); }
```
编译结果为:
```
#sidebar {
  width: 27px; 
}
```


**关于应用场景的思考:**
[SASS应用场景的思考](https://segmentfault.com/a/1190000009466690)

你可能感兴趣的:(Sass用法)