本文简单的介绍SASS预处理语言,更多的应用请参考官方文档
一、什么是SASS
二、为什么使用SASS
三、安装SASS
四、初次尝试SASS
数据类型
SASS中有着如下数据类型:
- 数字:
1
2
3
10px
- 字符串:
"foo"
'far'
baz
(注意baz为“无引号字符串”) - 颜色:
blue
#04a3f9
rgba(255, 0, 0, 0.5)
- 布尔值:
true
false
- 空值:
null
- 列表——用空格或者逗号分隔的一组值:
1.5em 1em 0 2em, Helvetica, Arial
- map——用小括号扩起的一组键值对集合
($key1: value1, $key2: value2, …)
- arglist——参数列表,函数中的变长参数
变量
-
定义变量:
$var_name : value;
SASS中变量的定义是宽松的,如果拿高级写的语言来考量的话会有时而是字符串时而是数字的疑惑,所以不要那么做,你不需要讲过多的注意力类型这一概念上。
$grayColor : darken(#FFFFFF, 20%); $width : 42px;
-
使用变量:SASS中的变量先声明后引用,(下文中引用到的变量$widht, #grayColor在上文中已经声明,本文以此缩短排版,这并不严谨有时有点滥用需要结合上下文)
div { color: $grayColor; width: $width; }
上面是SCSS代码,下面是对应的CSS代码,全文如不特殊说明一律采用这种方式
div { color: #cccccc; width: 42px; }
-
变量的
!default
关键字(前面的!
不能省)!default关键字表示:为该变量设置默认值,如果该变量已经声明过,则不改变原来值。
$var1: 12; $var1: 24 !default // var的值保持12不变
$var2: 24 !default // 直接声明并定义一个变量$var2,初始化值为24
-
局部变量
与全局变量
类似于大多数语言一样,SASS中拥有局部变量与全局变量的概念,这么做可以避免变量名重复,引用或更改到了不想更改的其它变量,造成系统的混乱。不包含在选择器,函数等块级结构之内,直接在文件中声明的变量称之为全局变量,反之则为局部变量。
$color: red; //全局变量 .blk { color: $color; //引用全局的$color,值为red } em { $color: orange; div { color: $color; //引用局部的$color,值为orange } }
.blk { color: red; } em div { color: orange; }
列表
CSS中存在有margin: 10px 15px 0 0
这类属性,为了便于处理这类情况SASS中存在有列表的数值类型,有点类似于大多数语言中的数组,列表需要将不同的类型的值用逗号
或者空格
分隔开,对于列表,SASS提供了一些函数进行处理:
$margins: 2px 4px 0 0;
.btn {
margin-top: nth($margins, 1); //列表的下标从1开始计算
}
.btn {
margin-top: 2px;
}
运算符
-
+
加法可以用于基本的数字相加,字符串连接
$width: 1px + 2in; $str: 'Hello ' + world; $margins: 12 12 12 1; .btn { width: $width + 4pt; font: $str; margin: margins + 2; }
.btn { width: 198.33333px; //不同的单位之间可以相加,但是不兼容的类型是不可以的,比如1px + 2em font: "Hello world"; //加法可以用于字符串的连接 margin: margins2; }
TIPS:
+
用于字符串连接时结果是否有引号跟加号左边的值保持一致,结果中的引号都会是双引号(如果想去掉可以加一层#{}
,或者使用unquote($string)
函数),而数字,列表等类型跟字符串连接之前会被转换成有引号字符串。结果是否有引号的规则还是按照前面所述。 -
-
减号自然不必多说,用于数值之间的减法,也需要操作数相互兼容,与
+
不同,-
不支持字符串操作。 -
*
乘号需要左右两个操作数至少有一个不带单位,不然会产生错误
.box { width: 10px * 2; height: 4 * 5pt; //height: 4pt * 5pt, 这么写会报错 }
.box { width: 20px; height: 20pt; }
-
/
除法有些特殊,因为在CSS中
/
已经挪作他用,所以在下列几种情况中才会有正常的表现,不然会作为CSS直接编译。- 被
()
扩起来:(100px / 2)
- 在表达式中:
1px + 100px / 2
$width / 4
// xxx.scss .btn { width: 100px /2; }
// xxx.css .btn { width: 100px /2; //这里的除法被原封不动的保存了 }
- 被
-
==
!=
>
<
>=
<=
基本的布尔运算返回值为
false
或true
-
if($condition, $if-true, $if-false)
其实if不是一个运算符而是一个函数,类似于c语言中的条件运算符,if函数当$condition为真返回$if-true,否则返回$if-false,注意这里的if不同于控制流中的
@if
注释
注释有以下两种风格
//这一段注释并不会显示在生成的CSS文件中
/*这一段注释会显示在生成的CSS文件中*/
嵌套
-
选择器嵌套,这里的选择器是CSS选择器
选择器嵌套针对的是标签的父子(包含)关系,如果B标签在A标签的内部,那么使用选择器嵌套语法再好不过,需要注意的是嵌套对可读性的影响,避免滥用选择器的嵌套。
现在有一段HTML:
<body> <div> <a href="##">Item1<a> <a href="##">Item2<a> <a href="##">Item3<a> </div> </body>
// xxx.scss div { a { color: red; body & { //这里的&表示当前块"div a" //body在&的前面,需要提出到全局去解析,不然是没有意义的 //也就是说这里是"body div a",而不是"div a body div a" color: green; } } }
// xxx.css div a { color: red; } body div a { color: green; }
-
属性嵌套
属性嵌套针对border-top这类使用
-
分割的属性,可以使用嵌套凸显层次性。.banner { border: { //注意border后面的":" top: 1px solid red; bottom: 2px solid green; } }
.banner { border-top: 1px solid red; border-bottom: 2px solid green; }
-
伪类嵌套
伪类嵌套很类似于选择器嵌套,需要借助&
.banner { &:before, &:after { content: ""; display: block; } }
.banner:before, .banner:after { content: ""; display: block; }
Mixin宏
可以使用“混入宏”打到样式的复用的目的
-
定义混入宏
-
不带参数
@mixin foo_bar { //foo_bar为宏的名字 -webkit-border-radius: 1px; -border-radius: 1px; }
-
带参数
@mixin foo_bar_with_arg($radius: 1px) { //参数$radius默认值1px -webkit-border-radius: $radius; -border-radius: $radius; }
-
-
使用混入宏
div { @include foo_bar_with_arg(2px); }
div { -webkit-border-radius: 2px; -border-radius: 2px; }
继承
SASS通过@extend
关键字使用继承,继承可以复用已存在的样式块。
.button {
border: 1px;
font-size: 1.5em;
}
.btn {
background-color: red;
@extend .button;
}
.button, .btn { //相对于@Mixin直接的文本替换,@extend继承显得更加智能,生成的CSS更简洁
border: 1px;
font-size: 1.5em;
}
.btn {
background-color: red;
}
占位符%placeholder
如果我需要继承一些CSS但是这些CSS不单独存在某些标签里该怎么办?
%baz { //不使用@extend调用的话%placeholder并不产生任何CSS代码
margin-top: 5px;
}
.btn {
@extend %baz;
margin-bottom: 10px;
}
#context a%foo { //这种诡异的形式也不会直接产生代码,需经过@extend
color: red;
width: 42;
}
.someots {
@extend %foo;
}
.btn {
margin-top: 5px;
}
.btn {
margin-bottom: 10px;
}
#context a.someots {
color: red;
width: 42;
}
插值#{}
插值是另一种本地替换的方式,有些类似于C语言中的宏定义
$arr: (top, bottom);
.btn {
@each $item in $arr { //暂未提及这里的@each in循环结构
margin-#{$item}: 42px;
}
}
.btn {
margin-top: 42px;
margin-bottom: 42px;
}
TIPS: 插值中又一点需要特别注意的是,所有的 <u>有引号字符串</u> 经过插值会转化为 <u>无引号字符串</u>
流程控制
-
@if
.block { @if 2 >= 3 { width: 200px; } @elseif 2 > 1 { width: 100px; } @else { width: 300px; } }
.block { width: 100px; }
-
@for
for循环有两种格式,分别以through,to两个关键字区分,for循环可以生成一个范围区间,并绑定一个变量给用户。
for $i from <start> through <end>
: $i从<start>到<end>(不包括<start>)for $i from <start> through <end>
: $i从<start>到<end>(包括<end>)@for $i from 1 through 3 { .block-#{$i} { width: 100px * $i; } }
.block-1 { width: 100px; } .block-2 { width: 200px; } .block-3 { width: 300px; }
循环可以极大的缩短CSS的代码量,有时CSS中的选择器可以达到效果,但是更多场景下灵活的SCSS利用循环可以极大的提高效率。
-
@while
@while用一个布尔量来决策循环是否结束。
$i: 1; @while $i <= 3 { .block-#{$i} { width: 100px * $i; } $i: $i + 1; }
.block-1 { width: 100px; } .block-2 { width: 200px; } .block-3 { width: 300px; }
-
@each
@each $var in <list>
: 遍历一个列表,绑定列表中的值到$var上。$nums: red yellow green; @each $color in $nums { .#{$color}_div { color: $color; } }
.red_div { color: red; } .yellow_div { color: yellow; } .green_div { color: green; }
常用函数
-
unquote($string)
quote($string)
这两个函数分别为字符串去除引号(只去除两端),添加双引号。
-
to-upper-case($string)
to-lower-case($string)
将字符串全部转换成大/小写。
-
一些数值函数
percentage($value)
: 将不带单位的数转换成百分数round($value)
: 将数值四舍五入ceil($value)
: 返回一个不小于$value的整数floor
: 返回一个不大于$value的整数abs($value)
: 返回$value的绝对值min($numbers...)
: 返回列表中最小的值max($numbers...)
: 返回列表中最大的值random()
: 获取一个随机数 -
一些列表函数
length($list)
: 返回列表长度nth($list, $n)
: 返回列表的第n个值join($list1, $list2, $separator: auto|comma|space)
: 合并两个列表append($list, $val, $peparator: auto|comma|space)
: 为列表追加值zip($lists...)
: 将多个列表压缩成多维度列表index($list, $val)
: 找到第一个与$val相等的值在$list中的下标p -
一些map函数
map-get($map, $key)
: 取得$map中$key键对应的值,没有则返回nullmap-has-key($map, $key)
: 判断$map中是否有键$keymap-keys($map)
: 返回$map中键的列表map-values($map)
: 返回$map中值的列表map-merge($map1, $map2)
: 返回包含$map1与$map2中所有键值对的一个新mapmap-remove($map, $key)
: 返回从$map中移除了$key为键的键值对的mapkeywords($args...)
: 按照给定的参数动态创建mapkeywords(c1: #fff, c2: #000)
-
内省函数
type-of($value)
: 返回值的类型unit($number)
: 返回数值的单位unitless($number)
: 判断值是否有单位comparable($number-1, $number-2)
: 判断两个值是否可以相互比较 -
颜色函数
rgb($red, $green, $blue)
: 生成RGB颜色rbga($red, $green, $alpha)
: 生成RGBA颜色rgba($color, $alpha)
: 返回$color改变透明度为$alpha之后的颜色red($color)
: 获取$color的红色分量green($color)
: 获取$color的绿色分量blue($color)
: 获取$color的蓝色分量mix($color-1, $color-2, $weight: 0.5)
: 混合两种颜色invert($color)
: 返回$color的反向色,rgb反向,alpha不变hsl
: 生成HSL颜色hsla
: 生成HSLA颜色hue($color)
: 返回$color的色相saturation($color)
: 返回$color的饱和度lightness($color)
: 返回$color的亮度adjust-hue($color, $degrees)
: 调整色相adjust-hue(#234f33, 45deg)
lighten($color, $amount)
: 变量颜色darken($color, $amount)
: 变暗颜色saturate($color, $amount)
: 增强饱和度desaturate($color, $amount)
: 降低饱和度grayscale($color)
: 返回$color对应的灰色complement($color)
: 返回与$color色相相反的颜色alpha($color)
: 获取透明度opacity($color)
: 获取透明度opacify($color, $amount)
: 降低透明度fade-in($color, $amount)
: 降低透明度transparentize($color, $amount)
: 增加透明度fade-out($color, $amount)
: 增加透明度
自定义函数
使用@function
关键字定义函数,可以问函数提供一个参数列表,在其中可以设置缺省参数,或者变长参数,如果函数有返回值需要使用@return
关键字。
@function foo($arg1, $arg2: 42, $args...) { //$arg2有默认值42,$args为变长参数
@debug 'foo get $arg1: ' + $arg1;
@debug 'foo get $arg2: ' + $arg2;
@debug 'foo get $args: ' + $args;
@return 0;
}
.btn {
width: foo(234, 43, 234, 2, 34, 234)
}
/*
控制台输出
DEBUG: foo get $arg1: 234
DEBUG: foo get $arg2: 43
DEBUG: foo get $args: 234, 2, 34, 234
*/
@规则
SASS支持所有的CSS的@规则,以及一些自己的扩展,也称为指令(directives)
-
@import
SASS扩展了CSS的@import规则,可以导入其他的SCSS文件,寻找文件的路径可以是当前目录,或者通过:load_path, —load-path配置
以下几种情况@import命令编译为CSS原生规则
- 导入文件扩展名为.css
- 导入文件名以
http://
开头 - 文件名为url()
- 如果@import包含媒体查询
@import "foo.css"; //后缀为css会编译为原生规则 @import "foo.scss"; @import "foo"; //导入文件可以不写后缀 @import "filea", "fileb"; //导入多个文件 @import "_fileignorecompile" //文件名之前加上_则只导入文件,不进行编译
-
@media
SASS中的@media可以嵌套在CSS规则中
.block { width: 100px; @media screen and (orientation: landscape) { //@media会浮出到最外层 width: 200px; } } //@media 是可以嵌套的 $media: screen; @media #{$media} { //在@media中使用插值 .btn { @media (orientation: landscape) { width: 500px; } } }
.block { width: 100px; } @media screen and (orientation: landscape) { .block { width: 200px; } } @media screen and (orientation: landscape) { .btn { width: 500px; } }
-
@at-root
at-root
可以让选择器跳出到嵌套中.foo { color: red; .bar { color: blue; @at-root .baz { color: white; } } }
.foo { color: red; } .foo .bar { color: blue; } .baz { //跳出了嵌套,不在层级结构中 color: white; }
-
@debug
@warn
@error
用于向控制台输出不同信息
@debug 'Hello, World!'; @warn 42; @error 'ops' + here is some error;