编译
使用 sass --watch
监控文件的改变,并对其进行实时编译
语法:
-
sass --watch input.sass:output.css
// 表示监控input.sass的改变,并实时编译,输出为output.css -
sass --watch input-dir:output-dir
// 监控input-dir文件夹下的所有sass或scss文件的改变,并实时编译到output-dir文件夹下
gulp的自动化编译脚本
需要安装gulp和gulp-sass
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task = ('sass', function(){
gulp.src('./scss/*.scss')
.pipe(sass({outputStyle: 'expressed'}).on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
gulp.task('watch', function(){
gulp.watch('scss/*.scss', ['sass']);
});
gulp.task('build-sass', ['sass', 'watch']);
.map文件
编译后生成的.map文件便于我们在浏览器中直接调试sass文件
常见的编译错误
除去编写sass的语法错误外,常见的编码错误有:
-
字符编码错误
在sass文件中将字符编码设置为:@charset "utf-8"
-
中文路径导致的错误
路径不要出现中文
编译后文件的输出风格
- 嵌套输出方式:nested
在编译时带上参数:--style nested
这种风格的大括号不占用一行 - 展开输出方式:expanded
在编译时带上参数:--style expanded
这种风格,大括号会另起一行 - 紧凑输出方式:compact
带上参数:--style compact
这种风格:单行css的形式 - 压缩输出方式:compressed
带上参数:--style compressed
这种风格:所有css在一行
语法
声明变量
sass的变量包含三个部分:
- 声明变量的符号 "$"
- 变量名称
- 赋予变量的值
如:
// 变量名为:width,值为:300px
$width: 300px;
// 如果值后面加上 `!default` 表示默认值
$fontSize: 14px !default;
两种形式变量:
普通变量: 如:
$width: 300px
-
默认变量:如:
$fontSize: 14px !default
如果要覆盖默认变量,只需要在它的前面重新声明即可$baseLineHeight: 2; $baseLineHeight: 1.5 !default; body{ line-height: $baseLineHeight; }
sass的变量有作用域
根据作用域的不同,分为:全局变量和局部变量
- 全局变量:定义在元素外部
- 局部变量: 定义在局部范围的变量,当局部变量与全局变量同名时,局部变量会覆盖全局变量
什么时候声明变量?
三个原则:
- 该值至少重复出现两次以上
- 该值至少可能会被更新一次
- 该值所有的表现都与变量有关(非巧合)
嵌套-选择器嵌套
三种嵌套方式:
-
选择器嵌套
如:nav { a { color: red; header & { color:green; } } } 转换为 css nav a { color: red; } header nav a { color: green; }
-
属性嵌套
有很多属性是有相同的前缀的,如:margin、padding、font等属性,可以像下面这样简写:.box { border: { top: 1px solid red; bottom: 1px solid green; } } // 转换为css .box { font-size: 12px; font-weight: bold; }
-
伪类嵌套
与属性嵌套非常类似,只不过需要借助"&"符号一起配合使用,如:.box{ &:before { content:"伪元素嵌套"; } } // 转换为css .box:before{ content: "伪元素嵌套"; }
混合宏
声明宏
-
不带参数混合宏
在sass中,使用"@mixin"来声明一个混合宏
如:
@mixin border-radius{
-webkit-border-radius: 5px;
border-radius: 5px;
}
@mixin
是用来申明混合宏的关键字,
border-radius
是混合红的名称,
大括号里面是复用的样式代码
-
带参数混合宏
在声明宏时带参数
@mixin border-radius($radius: 5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
-
复杂的混合宏
可以在大括号里面带有逻辑关系
如:
@if length($shadow) >= 1{
@include prefixer(box-shadow, $shadow);
} @else {
$shadow: 0 0 4px rgba(0, 0, 0, .30;
@include prefixer(box-shadow, $shadow);
}
注意:$shadown...
中的...
表示带有多个参数,当带有多个参数时,可以使用...
来代替,
@include
:表示调用混合宏
调用混合宏
sass中使用@mixin
声明混合宏,使用@include
调用混合宏
如:
// 声明一个border-radius 的混合宏
@mixin border-radius($radius: 5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
// 调用混合宏
button {
@include border-radius;
}
编译出来的css:
button {
-webkit-border-radius: 3px;
border-radius: 3px;
}
混合宏的不足
最大的不足是:生成冗余的代码块
如:
@mixin border-radius{
-webkit-border-radius: 3px;
border-radius: 3px;
}
.box {
@include border-radius;
margin-bottom: 5px;
}
.btn {
@include border-radius;
}
编译后的css:
.box {
-webkit-border-radius: 3px;
border-radius: 3px;
margin-bottom: 5px;
}
.btn {
-webkit-border-radius: 3px;
border-radius: 3px;
}
.box
和.btn
都调用了相同的内容,但是sass并未将其合并在一起,这便是混合宏最大的不足
扩展/继承
sass中的继承跟js中的继承类似,只不过它们继承的是样式,
sass中的继承通过@extend
, 如下代码:
// scss
.btn{
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary{
background-color: #f36;
color: #fff;
@extend .btn; //继承.btn
}
.btn-second {
background-color: orange;
color: #fff;
@extend .btn;
}
编译出来之后的css:
//CSS
.btn, .btn-primary, .btn-second {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary {
background-color: #f36;
color: #fff;
}
.btn-second {
background-clor: orange;
color: #fff;
}
通过继承便可以实现代码的复用,可以解决混合宏生成重复代码的问题
占位符 %placeholder
sass中的占位符功能很强大、很实用
使用占位符声明的代码块,如果没有被@extend
调用,就不会生成CSS代码,
可以取代以前CSS中的基类造成的代码冗余的情况。
如:
%mt5 {
margin-top: 5px;
}
%pt5 {
padding-top: 5px;
}
上面这段代码没有被@extend
引用,因此在编译时,不会生成冗余的CSS代码
如:
//SCSS
%mt5 {
margin-top: 5px;
}
%pt5{
padding-top: 5px;
}
.btn {
@extend %mt5;
@extend %pt5;
}
.block {
@extend %mt5;
span {
@extend %pt5;
}
}
编译出来的CSS
//CSS
.btn, .block {
margin-top: 5px;
}
.btn, .block span {
padding-top: 5px;
}
从编译出来的CSS代码可以看出,通过@extend调用的占位符,
编译出来的代码会将相同的代码合并在一起,这就是我们需要的
混合宏 VS 继承 VS 占位符
关于什么时候该用哪种方式,往往很纠结,以下分析:
- 混合宏的使用
//SCSS中混合宏使用
@mixin mt($var){
margin-top: $var;
}
.block {
@include mt(5px);
span {
display:block;
@include mt(5px);
}
}
.header {
color: orange;
@include mt(5px);
span{
display:block;
@include mt(5px);
}
}
编译出来:
.block {
margin-top: 5px;
}
.block span {
display: block;
margin-top: 5px;
}
.header {
color: orange;
margin-top: 5px;
}
.header span {
display: block;
margin-top: 5px;
}
结论: 从编译出来的css可以知道,使用混合宏时并不会合并相同的样式代码,造成代码的冗余,
但是它可以传递参数
建议:如果代码中涉及到变量,建议使用混合宏来创建相同的代码块。
-
sass中的继承
先上代码:
//SCSS 继承的运用
.mt{
margin-top: 5px;
}
.block {
@extend .mt;
span {
display:block;
@extend .mt;
}
}
.header {
color: orange;
@extend .mt;
span{
display:block;
@extend .mt;
}
}
编译出来的css:
.mt, .block, .block span, .header, .header span {
margin-top: 5px;
}
.block span {
display: block;
}
.header {
color: orange;
}
.header span {
display: block;
}
总结: 使用继承后,编译出来的CSS会将使用继承的代码块合并在一起,
通过组合选择器的方式展现, 相对于混合宏而言,要干净的多,但是,
继承不能传递参数
建议:如果代码块中不需要传递任何变量参数,而且有一个基类已在文件中存在,
那么建议使用sass的继承。
-
占位符
代码如下:
//SCSS中占位符的使用
%mt{
margin-top: 5px;
}
.block {
@extend %mt;
span {
display:block;
@extend %mt;
}
}
.header {
color: orange;
@extend %mt;
span{
display:block;
@extend %mt;
}
}
编译后的代码:
.block, .block span, .header, .header span {
margin-top: 5px;
}
.block span {
display: block;
}
.header {
color: orange;
}
.header span {
display: block;
}
总结:编译出来的css代码与使用继承的基本相同,只是不会在
代码中生成占位符mt的选择器,占位符和继承的主要区别:占位符是
独立定义,不调用的时候是不会在CSS中产生任何代码;继承是首先有
一个基类存在,不管调用与不调用,基类的样式都将会出现在编译后的的CSS代码中 。
插值#{}
如下代码:
$properties: (margin, padding);
@mixin set-value($side, $value) {
@each $prop in $properties {
#{$prop}-#{$side}: $value;
}
}
.login-box {
@include set-value(top, 14px);
}
编译出来:
.login-box {
margin-top: 14px;
padding-top: 14px;
}
数据类型
字符串
- 有引号字符串
- 无引号字符串
在编译CSS文件时不会改变其类型。只有一种例外:
使用#{}
插值语句时,有引号字符串将被编译为无引号字符串
如:
@mixin firefox-message($selector) {
body.firefox #{$selector}:before {
content: "Hi, Firefox users!";
}
}
@include firefox-message(".header");
编译为:
body.firefox .header:before {
content: "Hi, Firefox users!"; }
值列表
值列表就是:使用空格或逗号分隔的一些列的值
如:
margin: 10px 15px 0 0
//或
font-size: Helvetica, Arial, sans-serif
Sass列表函数赋予了值列表更多功能:
如:
- nth函数:可以直接访问值列表中的某一项
- join函数:可以将多个值列表串在一起
- append函数:可以在值列表中添加值
- @each函数:可以遍历值列表
运算
加法和减法运算
注意:在进行加减法运算时,如果单位不同,会出现报错
.box {
width: 20px + 10px;
}
乘法运算
注意:乘法与加减法略有不同,当两个值的单位相同时,只需要写上一个单位,否则会报错
如:
.box {
width: 10 * 2px; // 只需要写一个单位即可
}
如果改为如下所示,会报错:
.box {
width: 10px * 2px; // 两个值都加上单位,会报错
}
除法运算
因为除法运算符 “/” 在CSS中有特殊含义,如设置字体时添加行高,
因此,如果出现以下几种情况,“/” 会被当做除法,如:
- 如果数值或它的任意部分是存储在一个变量中或是函数的返回值
- 如果数值被圆括号包围(如果需要进行除法运算,直接使用圆括号包围最为保险)
- 如果数值是另一个数学表达式的一部分
示例如下:
//scss
p {
font: 10px/8px/ // 纯CSS, 不是除法运算
$width: 1000px;
width: $width / 2; // 使用了变量,是除法运算
width: round(1.5)/2; // 使用了函数,是除法运算
height: (500px / 2); // 使用了圆括号,是除法运算
margin-left: 5px + 8px/2px; // 使用了加(+)号,是除法运算
}
注意:当两个带有相同单位的数值进行除法运算时,最终会被编译为没有单位的css
.box {
width: (1000px / 100px);
}
编译出来的css:
.box {
width: 10;
}
颜色运算
sass中对颜色进行算术运算是分段运算的,也就是说,红、绿和蓝各个颜色分段单独进行运算
如:
p {
color: #010203 * 2;
}
字符运算
sass中通过加法符号 “ + ” 对字符串进行连接
如:
$content: 'hello' + '' + 'Sass!';
.box:before{
content: '#{$content}';
}