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 <start> through <end>和@for $var from <start> to <end>。$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 <list>。其中$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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • 学过CSS的人都知道,它并不是一种编程语言。 你可以用它开发网页样式,但是没法用它编程。也就是说,CSS基本上是设...
    小小奶狗阅读 292评论 0 0
  • 一、什么是SASS SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发...
    刘佳音阅读 377评论 0 1
  • 作者:阮一峰原文出处:http://www.ruanyifeng.com/blog/2012/06/sass.ht...
    IT程序狮阅读 946评论 2 3
  • 编译 sass的编译命令:sass input.css output.css真正使用场景下可以对整个文件夹进行监听...
    被注册的neil阅读 369评论 0 0
  • [toc] 前言 本文所有的演示都是基于Win10操作系统。 关于Sass 1.定义 Sass的学名叫“CSS预处...
    崔小叨阅读 18,211评论 0 78