程序员

CSS预处理器—Sass

Sass是一款非常流行易用的css预处理器

一、安装

安装Sass前请确认是否安装了ruby环境,ruby安装请移步ruby官网。
直接在命令行中输入

gem install sass

可能会因为天朝防火墙的原因,安装失败,这是我们需要更换安装源,我们使用淘宝的ruby镜像。

gem sources --remove https://rubygems.org
gem sources -a https://ruby.taobao.org
gem install sass

二、Sass基本命令

1、查看版本

sass -v

或者

sass --version

2、将sass文件编译为css文件

sass demo.scss:demo.css

3、监听文件变化或文件变化实时编译

sass --watch demo.scss:demo.css
sass --watch sassDir:cssDir

4、声明编译后的css文件风格
css文件风格的配置提供了四种,nested、expanded、compact、compressed

sass --watch demo.scss:demo.css --style compact

compressed常用于生产环境,至于开发环境看个人习惯,我一般是用expanded
5、查看sass命令帮助选项

sass -h

sass --help

sass -?

三、语法

1、变量
Sass变量必须以$开头。
局部变量

body{
    $color:red;
    color:$color;
}
body {
  color: red;
}

局部变量同级不能访问

body{
    $color:red;
    color:$color;
}
footer{
    color:$color;
}

这段代码报错
局部变量子级可以访问

body{
    $color:red;
    color:$color;
    h1{
        background:$color;
    }
}
body {
  color: red;
}
body h1 {
  background: red;
}

布局变量变为全局变量,在变量后添加!global

body{
    $color:red !global;
    color:$color ;
}
footer{
    color:$color;
}
body {
  color: red;
}
footer {
  color: red;
}

或者不在选择器中声明变量,在文件头部声明

$color:red;
body{
    color:$color ;
}
footer{
    color:$color;
}
body {
  color: red;
}
footer {
  color: red;
}

注意声明变量同样会被覆盖

$color:red;
$color:blue;
body{
    color:$color ;
}
footer{
    color:$color;
}
body {
  color: blue;
}
footer {
  color: blue;
}

变量后添加!default为变量默认值。
多值变量,可以根据自己的需要选择相应的值

$paddings: 10px 20px 30px 40px;
body{
    padding:$paddings;
    padding-left:nth($paddings,2);
}
body {
  padding: 10px 20px 30px 40px;
  padding-left: 20px;
}

同时多值变量可以用map数据,以key—value形式出现

$maps:(color:red, border:1px solid #eee);
body{
    color:map-get($maps, color);
    border: map-get($maps, border);
}
body {
  color: red;
  border: 1px solid #eee;
}

变量一般是当做属性值来使用的,但是如果变量作为属性或者在某些特殊情况下等则必须要以#{$varialbes}形式使用

$direction: top;
$className: container;
.#{$className}{
    border-#{$direction}:1px solid #eee;
}
.container {
  border-top: 1px solid #eee;
}

当然sass的变量可以使用中划线也可以使用下划线,这完全取决于你的习惯。

$font-size:12px;
$border_style:1px solid #eee;
body{
    font-size:$font-size;
    border:$border_style;
}
body {
  font-size: 12px;
  border: 1px solid #eee;
}

sass编译的时候中划线和下划线是等同的,因此你甚至可以像下面一样随意使用,但是这当然是不推荐的

$font-size:12px;
$border_style:1px solid #eee;
body{
    font-size:$font_size;
    border:$border-style;
}
body {
  font-size: 12px;
  border: 1px solid #eee;
}

2、引入
sass中我们默认部分文件的文件名以下划线开头,这样监听文件夹的时候就不会将这个部分文件编译为css文件,引入部分文件时,我们可以写文件全称,也可以省略后缀名,甚至可以去掉下划线

@import "_part.scss";
@import "_part";
@import "part.scss";
@import "part";

3、嵌套
选择器嵌套

body{
    background-color:#eee;
    .header{
        background-color:#ccc;
        font-size:16px;
        &-container{
            margin:0 auto
        }
    }
}
body {
  background-color: #eee;
}
body .header {
  background-color: #ccc;
  font-size: 16px;
}
body .header-container {
  margin: 0 auto;
}

属性嵌套

body{
    background:{
        color:red;
        repeat:no-repeat;
    }
}

···
body {
background-color: red;
background-repeat: no-repeat;
}
···
可以通过地址符号&引用父选择器

a{
    color:#000;
    &:hover{
        color:#eee;
    }
}
.container{
    width:200px;
    &-info{
        height:20px;
    }
}
a {
  color: #000;
}
a:hover {
  color: #eee;
}
.container {
  width: 200px;
}
.container-info {
  height: 20px;
}

我们可以使用@at-root跳出选择器嵌套,当然这种使用方法常常是在嵌套比较深,我们不想嵌套这么深,但是在结构上这个又是属于父级的

body{
    .container{
        @at-root .info{
            color:#fff;
        }
    }
}
.info {
  color: #fff;
}

当然这并不能跳出媒体查询,如果需要跳出媒体查询的话需要使用@at-root (without: media)

@media screen and (max-width:1200px) {
    @at-root .container{
        height:300px;
    }
    @at-root (without:media) {
        .container{
            height:200px;
        }
    }
}
@media screen and (max-width: 1200px) {
  .container {
    height: 300px;
  }
}
.container {
  height: 200px;
}

这里的without有四个关键字media、rule、all、support,media表示跳出媒体查询,rule表示跳过普通css,all表示跳出所有,support不怎么使用,在此不表。
4、继承
sass中可以让选择器继承另一个选择器的所有样式,继承的样式编译后会采用联合声明,继承时采用@extend关键字

.container{
    margin:0 auto;
}
.title{
    @extend .container;
    border:1px solid #eee;
}
.container, .title {
  margin: 0 auto;
}
.title {
  border: 1px solid #eee;
}

继承多个选择器样式时,可以多次使用@extend,也可以使用逗号分隔需要继承的选择器

.container{
    margin:0 auto;
}
h1{
    font-size:12px;
}
.title{
    @extend .container;
    @extend h1;
    border:1px solid #eee;
}
.container{
    margin:0 auto;
}
h1{
    font-size:12px;
}
.title{
    @extend .container,h1;
    border:1px solid #eee;
}
.container, .title {
  margin: 0 auto;
}
h1, .title {
  font-size: 12px;
}
.title {
  border: 1px solid #eee;
}

当然也可以使用链式继承,不断继承

.container{
    margin:0 auto;
}
h1{
    font-size:12px;
}
.title{
    @extend .container,h1;
    border:1px solid #eee;
}
.info{
    @extend .title;
    border-radius:5px;
}
.container, .title, .info {
  margin: 0 auto;
}
h1, .title, .info {
  font-size: 12px;
}
.title, .info {
  border: 1px solid #eee;
}
.info {
  border-radius: 5px;
}

注意继承时,多选择器和毗邻兄弟选择器不支持继承,以下代码会报错

h1 span{
    font-size:15px;
}
h2{
    @extend h1 span;
}
h1 + span{
    font-size:15px;
}
h2{
    @extend h1 + span;
}

同时如果继承的选择器中有:hover这种伪类,同时也会被继承

.h1{
    font-size:15px;
    &:hover{
        color:red;
    }
}
.h2{
    @extend .h1;
    color:#000;
}
.h1, .h2 {
  font-size: 15px;
}
.h1:hover, .h2:hover {
  color: red;
}
.h2 {
  color: #000;
}

注意继承是不能继承自media之外的选择器的,以下代码会出错

.one{
    color:red;
}
@media screen and (max-width:1200px){
    .two{
        @extend .one;
    }
}

当你只是想把继承而来的选择器作为一种过渡,不想让它最终编译在css文件中,你可以使用占位选择器%

%footer{
    font-size:20px;
}
footer{
    @extend %footer;
    background:#eee;
}
footer .title-container{
    @extend %footer;
    line-height:1.5em;
}
footer, footer .title-container {
  font-size: 20px;
}
footer {
  background: #eee;
}
footer .title-container {
  line-height: 1.5em;
}

这非常适合将公共的样式分离出来。
5、混合
混合非常适合用来定义一些可重用的CSS代码片段,混合以@mixin定义,以@include使用,混合甚至可以使用参数,这就大大拓展了使用场景(当然如果没有参数,和使用选择器占位符的继承也没有区别)

@mixin cont{
    color:red;
}
body{
    @include cont;
}
body {
  color: red;
}
@mixin opacity($opacity:80){
    opacity:$opacity / 100;
    filter:alpha(opacity = $opacity)
}

body{
    background:red;
    @include opacity;
}
.con{
    @include opacity(50);
}
body {
  background: red;
  opacity: 0.8;
  filter: alpha(opacity=80);
}
.con {
  opacity: 0.5;
  filter: alpha(opacity=50);
}

使用参数的时候可以使用多个参数,当然你需要按照定义的顺序传递参数,如果你不想按顺序传参或者并不是需要传递全部参数,就需要在传递参数的时候采用键值对形式

@mixin mix($font-size:14px,$color:red){
    font-size:$font-size;
    color:$color;
};
.class1{
    @include mix(16px,#eee);
}
.class2{
    @include mix($color:blue);
}
.class1 {
  font-size: 16px;
  color: #eee;
}
.class2 {
  font-size: 14px;
  color: blue;
}

当我们不知道需要传递参数的个数时,我们可以在参数后面加…来表示,这通常是在background、box-shadow等可以定义多个值时使用

@mixin shadow($value...){
    box-shadow:$value;
}
.your-selector{
    @include shadow(0px 5px 5px #333,0px 10px 10px #555);
}
.your-selector {
  box-shadow: 0px 5px 5px #333, 0px 10px 10px #555;
}

混合还可以使用@content来接受一整块样式,这在响应式web设计中非常有用

@mixin style-for-iphone{
    @media screen and (min-width:320px) and (max-width:568px){
        @content;
    }
}
@include style-for-iphone{
    .mycontainer{
        width:98%;
    }
}
@media screen and (min-width: 320px) and (max-width: 568px) {
  .mycontainer {
    width: 98%;
  }
}

6、函数
sass中提供了很多函数,具体的函数可以在这里查到http://sass-lang.com/documentation/Sass/Script/Functions.html其中sass中的rgb函数可以将一个rgb颜色转换为十六进制颜色值

body{
    color:rgb(200,200,200);
}
body {
  color: #c8c8c8;
}

rgba函数可以将一个颜色值根据给定的透明度来转换为rgba颜色值

body{
    $color:rgb(200,200,200);
    color:$color;
    background:rgba($color,0.65);
}
body {
  color: #c8c8c8;
  background: rgba(200, 200, 200, 0.65);
}

此外sass中提供了很多其他的内置函数,不过在实际工作中用得会比较少,我们也可以通过@function关键字来自定义函数。

@function myfunction($width){
    @return $width * 2;
}
.myclass{
    width:myfunction(30px);
}
.myclass {
  width: 60px;
}

7、条件判断
if可以提供三目运算的功能,语法为if(value, value1, value2)当value为真时,采用value1的值,否则采用value2的值。

$screen:800;
body{
    font-size:if($screen > 768, 14px, 12px);
}
body {
  font-size: 14px;
}

@if、@else if、@else可以提供判断的功能。

$screen:700;
@if $screen > 768{
    body{
        color:red;
    }
}
@else if $screen > 560{
    body{
        color:blue;
    }
}
@else{
    body{
        color:yellow;
    }
}
body {
  color: blue;
}

8、循环
@for关键字可以提供循环功能,有两种语法

@for $var from  through 

@for $var from  to 

两种区别是through中包含end,而to不包含

@for $i from 1 through 3{
    .span-#{$i}{
        width:20% * $i;
    }
}
.span-1 {
  width: 20%;
}
.span-2 {
  width: 40%;
}
.span-3 {
  width: 60%;
}
@for $i from 1 to 3{
    .span-#{$i}{
        width:20% * $i;
    }
}
.span-1 {
  width: 20%;
}
.span-2 {
  width: 40%;
}

显然这非常适合数字连续的多个类的样式书写。
同样也可以使用@each实现遍历

$i:1;
@each $c in blue,red,green {
    .div#{$i}{
        color:$c
    }
    $i: $i + 3;
}
.div1 {
  color: blue;
}
.div4 {
  color: red;
}
.div7 {
  color: green;
}

7、调试
sass的调试可以使用@debug、@warn、@error三个关键字进行调试,相关信息将会在控制台输出

@debug "this is a bug";