SASS,全称Syntactically Awesome StyleSheets,是基于Ruby语言的一个CSS预处理工具,顾名思义就是在css使用之前进行一系列的处理,使其能够自适应某些特定场合。
安装
如果是windows系统,那就要先安装Ruby和gem,再通过gem来安装SASS。(Ruby的gem可以看作为Node的npm,都是方便的包管理工具),sass也有node的版本,但因为墙的原因安装比较麻烦,需要先安装cnpm,再安装node-sass。我用的node版。
通过淘宝镜像安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
通过cnpm安装node-sass到项目
cnpm install --save-dev node-sass
sass有两种格式的写法,分别是严格模式下的sass,不能使用分号和大括号;另外一种是非严格模式下的scss,跟css类似可以使用分号和大括号。建议使用scss来进行编写。
单次编译,把scss文件编译为浏览器可读的css
node-sass input.scss:output.css
可以开启文件监视模式自动保存并编译:(input.sass为在编辑的文件,output.css为编译后的文件)
node-sass --watch input.scss:output.css
语法
SASS拓展了CSS的很多功能,使CSS变得更加灵活,更加像一门“语言”。
导入
来看一个例子
//a.scss
.a{color:"red";}
//b.css
.b{color:blue;}
//c.scss
@import "a"
@import "b.css"
.c{color:black;}
//编译后的c.css
@import "b.css"
.a{color:red;}
.c{color:black;}
可以看出几个规律:在scss文件中导入css文件的话,会保持import的形式;而导入scss文件的话,则会进行合并(并且可以省略scss尾缀)。
嵌套
.wrapper{
font-size:13px;
.item{
color:white;
}
}
等同于:
.wrapper{
font-size:13px;
}
.wrapper .item{
color:white;
}
使用@at-root跳出嵌套:
//scss
.parent{
width:2px;
@at-root .child{
color:red;
}
}
//css
.parent{
width:2px;
}
.child{
color:red;
}
父选择器
.wrapper{
font-size:13px;
$:hover{color:black;}
body ${line-height:20px;}
}
等同于:
.wrapper{
font-size:13px;
}
.wrapper:hover{
color:black
}
body .wrapper{
line-height:20px;
}
(注意,如在body选择器后使用$的话,会脱离嵌套结构独立出来一个以body开头的语句(说实话感觉没什么用))
$还可以以字符的形式进行拼合:
.wrapper{
$-top{height:100px;}
}
等同于:
.wrapper-top{
height:100px;
}
属性嵌套
.item{
font:{
size:13px;
family:微软雅黑;
}
}
等同于:
.item{
font-size:13px;
font-family:微软雅黑;
}
注释
SASS的注释与js相同,单行//,多行/**/,但是只有多行的注释会被输出到编译后的文件中,要注意。
变量
SASSscript,SASS赋予了CSS属性使用变量,算数运算等功能。
先看看变量的使用:
$width:15px;//使用$进行变量的定义,这里是全局作用域,所以是全局变量
.wrapper{
$height:20px!global;//在嵌套作用域中定义时,加上!global可以转变为全局变量
$bgc:white;//在嵌套作用域中定义,是局部变量
width:$width;//变量的使用
}
.item{
background-color:$bgc;//报错,因为$bgc是.wrapper的局部变量
height:$height;//OK,$height是全局变量
}
默认变量
在定义变量的时候在句末加上!default就可以为变量定义默认值,在默认变量之前再定义一次变量就可以设定我们需要的值
//scss
$width:2px;
$width:10px!default;
.a{width:$width;}
//css
.a{width:2px;}
特殊变量,使用#{变量}来进行变量的特殊引用
看个例子
//scss
$des:top;
$widtha:10px;
$widthb:20px;
margin-#{top}:30px; //用在属性上
font:#{widtha}/#{widthb}; //用在复杂属性值上
//css
margin-top:30px;
font:10px/20px;
多值变量
list,类似于js中的数组
$px:1px 2px 3px 4px; //以空格隔开
$px:1px 2px,3px 4px; //以逗号隔开
$px:(1px 2px) (3px 4px); //以空格隔开括号
可以用nth来取值:
//scss
$px:2px 4px;
width:nth($px,2);
//css
width:4px;
map,类似js中的对象,以键值对形式出现
//sass
$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
#{$header} {
font-size: $size;
}
}
//css
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
有点像js的for in
混合
@mixin用来定义一套内容,使用@include使用,还可以使用参数来调整内容
//scss
@mixin a{ //不带参数
color:red;
}
@mixin b($size){ //带参数
font-size:$size;
}
@mixin c(@width:10px){ //参数带默认值
width:$width;
}
p{
@include a;
@include b(12px);
@include c;
}
//css
p{
color:red;
font-size:12px;
width:10px;
}
@mixin功能很强大,可以方便管理一些重复出现的内容(如各种浏览器内核的前缀)。
@content,为了解决css3@media带来的问题而引入的功能:
//scss
@mixin max-screen($res){
@media only screen and ( max-width: $res )
{
@content;
}
}
@include max-screen(480px) {
//这里输入@content的内容
body { color: red }
}
//css
@media only screen and (max-width: 480px) {
body { color: red }
}
数据类型
SASSscript支持六种主要数据类型:
数字:1,12,13px;(是的,带px的也算)
字符串:“你好”,“123”;
颜色:#223344,rgb(10,10,10),blue;
布尔:true,false;
数组:1 2 3 4;1,2,3,4;(可以用空格或逗号做分隔,实际上单个值也会被看作是数组);
运算
结合变量和数据类型,我们就可以使用SASS中最实用的功能:属性值的运算
CSS是没有运算功能的,例如我们想要把两个元素的长度相加,那么就需要通过JS把两个长度单独取出,用变量保存再相加,最后再转成CSS属性。
SASS提供的运算功能直接体现在SASS文件中,通过编译转化成为CSS,更加方便快捷。
数据运算可以使用+-*/%(加减乘除取整)等符号,关系运算可以使用<,>,<=,>=,以上两种运算只能用于数字,相等运算(==,!=)可以用于所有数据。
()括号可以影响运算顺序,与js类似。
/符号在CSS中用作分隔数字:font:10px/20px;(字体大小/行高),在SASS中可用作除法运算。
只有在以下情况中/号才会被当作除法运算符号:
属性值或属性值的一部分是变量或者函数返回值:width:$width/2;
属性值被括号包围:width:(500px/2);
属性值是表达式的一部分:width:100px+500px/2;
如果想要在使用变量的同时使用/的分隔功能的话,可以使用#{}:font:#{$size}/#{$height};
颜色值也是可以运算的,以rgb为基础,对三个值进行单独运算再结合:
p{
color:#010203+#010101;//01+01,02+01,03+01=#020304
color:#010203*2;//01*2,02*2,03*2=#020406
color:rgba(1,1,1,0.5)+rgba(2,2,2,0.5);//rgba(3,3,3,0.5),注意alpha通道不参与计算
}
字符串的运算
字符串分为带引号字符串和不带引号字符串,跟js类似,可以用+号进行字符串合并:
p{
font-family:sans- + "serif";//sans-serif,注意,+号前有引号,则结果有引号,+号前没引号则结果没引号
margin:3px + 4px auto;//7px auto,运算后与其他值连用时,用空格隔开
}
p:before{
content:"i have #{2+5} car";//"i have 7 car",使用#{}来进行字符串内插值
}
布尔值可以使用and or not进行运算,数组不支持任何运算方式,只能使用函数
条件判断和循环
@if和@else
//scss
$state:active;
.a{
@if $state==active{
color:green;
}@else if $state==wait{
color:gray;
}@else{
color:black;
}
}
//css
.a{color:green;}
也可以单独使用@if作真值判断,或者使用三元判断的形式:
//scss
$visible:true;
.a{
display:if($visible,block,none);
}
//css
.a{
display:block;
}
for循环
//scss
@for $i from 1 to 3{
.page-#{$i} {width:$i * 2px;}
}
@for $i from 1 through 3{
.content-#{$i} {width:$i * 3px;}
}
//css
.page-1{width:2px;}
.page-2{width:4px;}
.content-1{width:3px;}
.content-2{width:6px;}
.content-3{width:9px;}
上面演示了to和through的差别,前者不包括结尾数3,后者包括
@each循环
上面说了map的循环,这里说一下list的循环:
//scss
$color-list:red blue green;
@each $color in $color-list{
.color-#{$color}{color:$color};
}
//css
.color-red{color:red;}
.color-blue{color:blue;}
.color-green{color:green;}
多字段list的循环
//scss
$list:(1,red,2px) (2,blue,4px) (3,green,6px);
@each $num,$color,$width in $list{
.page-#{$num}{
color:$color;
width:$width;
}
}
//css
.page-1{color:red;width:2px;}
.page-2{color:blue;width:4px;}
.page-3{color:green;width:6px;}