Sass 基础知识速查。

Sass 是一个 CSS 的语言扩展, 让工程中样式风格配置等维护变得更容易。Sass 实际是一个预处理器,开发者通过 Sass 语法编写代码,然后将这些 Sass 代码转换为 CSS。

Sass 有两种语法:

  • SCSS: 新语法
  • Sass: 老语法,通过缩进而非括号的方式来识别嵌套的选择器。

下面介绍的均为新语法,且仍然使用 “Sass” 字样,不再作重复说明。

变量:Sass 变量定义和使用

Sass 中使用 $ 符号定义变量,如: $text-color. 定义和使用变量的方式如下所示:

sass
$text-color: red;

.header{
  text-align: $text-color;
}

.blog-post, h2 {
  color: $text-color;
}

嵌套:Sass 中的风格嵌套

传统的 CSS 编写时,通过如下方式定义嵌套风格:

css
nav {
  background-color: red;
}

nav ul {
  list-style: none;
}

nav ul li {
  display: inline-block;
}

而使用 Sass 时,可以用嵌套的括号来表达这样的关系:

css
nav {
  background-color: red;
  ul {
    list-style: none;
    li {
      display: inline-block;
    }
  }
}

并且可以直接在里面写相同的 css 代码。实践中可以像这样:

html
<style type='text/scss'>
  .blog-post {
    h1 {
        text-align: center;
        color: blue;
    }
    p {
        font-size: 20px;
    }
  }
</style>

<div class="blog-post">
  <h1>Blog Title</h1>
  <p>This is a paragraph</p>
</div>

函数:通过 Mixin 创建可重用配置

在 Sass 中,mixin 用于定义一组可重用的 CSS 声明,这样 mixin 就可以在其他地方重复使用了。(比较类似普通编程语言中的函数)

比如下面的 CSS 用于根据不同的浏览器定义不同的 shadow(有不同的 vendor prefix):

css
div {
  -webkit-box-shadow: 0px 0px 4px #fff;
  -moz-box-shadow: 0px 0px 4px #fff;
  -ms-box-shadow: 0px 0px 4px #fff;
  box-shadow: 0px 0px 4px #fff;
}

如果工程中有若干个元素都需要使用 box-shadow,则会重复写很多这样的代码,此时就可以定义 mixin 处理重复:

css
@mixin box-shadow($x, $y, $blur, $c){ 
  -webkit-box-shadow: $x $y $blur $c;
  -moz-box-shadow: $x $y $blur $c;
  -ms-box-shadow: $x $y $blur $c;
  box-shadow: $x $y $blur $c;
}

而使用的时候也非常类似函数调用:

css
div {
  @include box-shadow(0px, 0px, 4px, #fff);
}

有需要的地方只用按上面的语法来调用,并传入参数即可,比如按照这个套路定义一个可重用的边框圆角配置:

html
<style type='text/scss'>

  @mixin border-radius($radius) {
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    -ms-border-radius: $radius;
    border-radius: $radius;
  }

  #awesome {
    width: 150px;
    height: 150px;
    background-color: green;
    @include border-radius(15px);
  }
</style>

<div id="awesome"></div>

逻辑控制:使用 @if@else

在 Sass 中还可以写逻辑控制,特别是在 mixin 中。比如下面的代码就是完整的 if-elseif-else 的示例:

css
@mixin text-effect($val) {
  @if $val == danger {
    color: red;
  }
  @else if $val == alert {
    color: yellow;
  }
  @else if $val == success {
    color: green;
  }
  @else {
    color: black;
  }
}

比如代码中想通过传入风格变量来设置不同的边框,则可以像下面这样:

html
<style type='text/scss'>

  @mixin border-stroke($val) {
    @if $val == light {
      border: 1px solid black;
    }
    @else if $val == medium {
      border: 3px solid black;
    }
    @else if $val == heavy {
      border: 6px solid black;
    }
    @else {
      border: none;
    }
  }

  #box {
    width: 150px;
    height: 150px;
    background-color: red;
    @include border-stroke(medium);
  }
</style>

<div id="box"></div>

for 循环:使用 @for

下面的例子演示使用 @for 来非常巧妙地处理多个字体大小的场景,另外演示了如何在 Sass 中带变量来计算,以及如何插入变量值:

html
<style type='text/scss'>

@for $j from 1 through 6 {
    .text-#{$j} {
        font-size: 15px * $j;
    }
}

</style>

<p class="text-1">Hello</p>
<p class="text-2">Hello</p>
<p class="text-3">Hello</p>
<p class="text-4">Hello</p>
<p class="text-5">Hello</p>

上面看到, 通过 .text-#{$j} 这样的方式将变量的值插入到 class selector 中,并且直接可以使用变量进行计算(乘法计算)。

for-each 循环:使用@each将元素列表进行处理

类似 @each 的作用就类似 for-in,比如下面这个例子生成三个颜色配置 class selector:

css
@each $color in blue, red, green {
  .#{$color}-text {color: $color;}
}

比如也可以定义变量来处理,上面的例子可以这样写:

css
$colors: (color1: blue, color2: red, color3: green);

@each $key, $color in $colors {
  .#{$color}-text {color: $color;}
}

不过这样写的话必须将键值对分离(key 和 color),否则列出的内容就只有 key 而没有值了。

上面两个例子转换后的 CSS 如下:

css
.blue-text {
  color: blue;
}

.red-text {
  color: red;
}

.green-text {
  color: green;
}

仿照上面的内容,可以写将三个 div 设置不同背景色的代码:

html
<style type='text/scss'>

  @each $color in blue, black, red {
    .#{$color}-bg {
      background-color: $color;
    }
  }

  div {
    height: 200px;
    width: 200px;
  }
</style>

<div class="blue-bg"></div>
<div class="black-bg"></div>
<div class="red-bg"></div>

while 循环: 使用 @while

使用 @while 可以循环直至条件不满足为止:

css
$x: 1;
@while $x < 13 {
  .col-#{$x} { width: 100%/12 * $x;}
  $x: $x + 1;
}

循环生成 col-x 这样的 class selector 并设置宽度。

另外可以看到,变量赋值的话使用的是 :

仿照例子,编写如下循环实现不同 class 的字体配置:

html
<style type='text/scss'>

$x: 1;
@while $x < 6 {
    .text-#{$x} {
        font-size: 15px * $x;
        $x: $x + 1;
    }
}

</style>

<p class="text-1">Hello</p>
<p class="text-2">Hello</p>
<p class="text-3">Hello</p>
<p class="text-4">Hello</p>
<p class="text-5">Hello</p>

Partial 和 @import: 通过 partial 组织可重用的代码

Partial 在 Sass 中用于分离不同的 CSS 代码段,这样可以将 Partial 作为模块引入到其他的 Sass 文件中。

Partial 使用 _ 下划线开头命名,这样告诉 Sass 这个文件不是独立文件,而是一个部分,这样就不会单独将它转换为 CSS 了。

使用 @import 来在其他 Partial 或独立 Sass 文件中引入 Partial。

比如定义了一个 Partial 为 _variables.scss,要引入它,则:

css
@import 'variables'

需要注意的是: 在引入的时候不要在 Parital 的名字中携带下划线,且不带后缀,且用引号括起来。。。

继承:使用 @extend 重用已定义的配置

比如定义了一个 class 为 panel

css
.panel{
  background-color: red;
  height: 70px;
  border: 2px solid green;
}

其他地方要重用里面的部分或全部配置,则可以使用 @extend

css
.big-panel{
  @extend .panel;
  width: 150px;
  font-size: 2em;
}

如下是一个简单的例子:

html
<style type='text/scss'>
  h3{
    text-align: center;
  }
  .info{
    width: 200px;
    border: 1px solid black;
    margin: 0 auto;
  }

  .info-important {
    @extend .info;
    background-color: red;
  }


</style>
<h3>Posts</h3>
<div class="info-important">
  <p>This is an important post. It should extend the class ".info" and have its own CSS styles.</p>
</div>

<div class="info">
  <p>This is a simple post. It has basic styling and can be extended for other uses.</p>
</div>