Sass预处理

106 阅读6分钟

一 css预处理是什么

css是描述性语言,不能像js使用编程式方法写,变量、循环。运算等无法使用。css预处理解决了这个问题,可以编程式写css,写变量、循环、函数等。术语是这样,但其实就是更简单的css书写格式,常见的有3种:Sass/Less/stylus。
今天主要讲清楚Sass

二 Sass和Less的区别

这俩是目前应用最广的,语法类似,区别如下: 1. 底层实现语言不同:Sass是Ruby实现,编译时在服务端处理;Less是js编写,编译时在浏览器处理; 2. Sass功能更强大:Sass有循环、函数、混合宏等;Less没有; 3. Sass有框架可以辅助开发,如Compass,Less没有; 4. 因此Sass在国内外讨论更多,使用更多;

三 Sass和Scss的语法格式

Sass有2种语法格式:Sass和Scss。我更偏向于用Scss,语法跟css相近,而Sass的语法与Ruby相近。

Sass语法格式:

相似Ruby,严格的缩进。

Scss语法格式:

相似css,{}和;

1. 变量

变量的来源可以是css中定义的,也可以是js中的。js中可以是data里的,也可以是标签内:style定义的,或者是父组件内定义后子组件直接引用。

(1. 变量声明

声明,例声明,例 ` color:red,调用:color: $color; `

变量有一般值和默认值,默认值的写法:变量有一般值和默认值,默认值的写法:color:red !default;顾名思义,默认值可以被同名变量覆盖。

(2. 变量作用域

类似js的变量作用域,有全局和局部。局部比如说选择器内,混合宏内,继承样式内等。例:一个同名变量,全局和局部都有,优先调用局部的。

$width: 100px;
div{
    $width: 200px;
    width: $width;
}
* 解析为200px,选择器内的局部变量

(3. 变量的值可以有7种

  1. 数字:也可结合css单位,例1.5,10px,50%等;
  2. 字符串:css内的字符串同等拿过来设置就可,有无引号跟css值保持一致。如bold,"黑体";
  3. 布尔值:跟@if...@else一起使用;
  4. 颜色值,类似css的关键字、rgba、16进制等颜色格式;
  5. 列表:变量值可以是list,例margin的4个值就是空格隔开的list;font-family是,隔开的list;
  6. map值:键值对,在这里语法是(key1:val1, kay2:val2, key3:val3)

2.插值,#{}

其实还是变量的使用,只是用来表示名称等,加个#{}做区分。
在“选择器名”、"属性名"、“属性值”中插入一个变量值,而构成一个新选择器名,离nth-child($i),常见用法。可结合循环@for使用

@for $i 1through 3 {
    nth-child(#{$i}){
        border-width: $ipx
    }
}

3. 嵌套

3种嵌套方式都比较常用:选择器、属性、伪类,使用方便简单非常好。但是考虑到解析难度,一般控制在3层内。

// 1.最常见的选择器嵌套
.wrap{
    ...
    .nav{
        ...
    }
}
// 2.属性嵌套,可减少一定的代码书写量,一定记得冒号:
div{
    ...
    margin:{
        top: 10px;
        right: 0;
        bottom: 0;
        left: 10px;
    }
}
// 3.伪类、伪元素嵌套,结合&:符号,也常用
div{
    color: $color;
    &:hover{
        color: $red
    }
}

4.注释

3种常见注释格式都行:

1. // ...
2. /* ... */
3. /*! ... */

5.基本运算

css有计算属性calc,但是能做的有限。Sass提供了类似js的各种运算。有3种运算形式:数字、字符、颜色。

(1.数字运算

类似js,数字可以加减乘除,可以带单位,但是单位要相同,否则报错Incompatible units。

$width: 100px;
// 1. 加减法一样简单。
div{
    width: $width + 20px;   //120px
}
// 2.乘法理解为一个值的n倍,所以倍数n不能带单位。
div{
    width: ($width *  2);    //200px
    width: ($width * 2px);    // 报错200px*px isn't a valid CSS value 
}
@for $i 1through 3{
    .item_#{$i}{
        width: 10px * $i;
    }
}
// 3.除法的语法格式是/,但是因为这个“/”在css中常用作其他意义,所以常量计算要加()
div{
    height: (100px / 2);   //常量计算
    height:  $width / 2;    //变量计算可以不加()
}

(2.字符运算,也就是拼接

as is known to all,scss里的字符串存在有无引号两种情况,那么拼接后有无引号?不管右边有无引号,跟随左边的引号情况。

(3.颜色运算

As we know, scss里的颜色支持多种写法,解析器会转为16进制颜色后计算:

color: #010203 + # 040506;
color: #010203 * 2;
color: (rgba(17, 32,34) * 2);

6.代码重用

这个很好用,传统css会有很多重复代码,我们只能通过提取公共样式复用。scss里提供了3种复用手段,更加灵活:

  1. 继承@extend
  2. 占位符%placeholder
  3. 混合宏@mixin

(6.1 scss继承

使用@extend继承一个样式块。继承的解析,是要添加继承人的;混合宏是要混入到下面的引用块里。

.box{
    width: 100px;
    height: 100px;
}
.box_1{
    @extend .box;
    color: red;
}
// 解析后,相当于给.box代码块增加并列选择器,如下:
.box, .box_1{
    width: 100px;
    height: 100px;
}
.box_1{
    color: red;
}

(6.2 Sass占位符placeholder

占位符%可进一步优化extend,不是取代,而是配合extend使用。

%btn{
    padding: 6px 10px;
    font-size: 14px;
}
.btn_1{
    @extend %btn;
    color: red;
}
// 解析后,如果没用到的类名会自动省略,如下:
.btn_1{
    padding: 6px 10px;
    font-size: 14px;
}
.btn_1{
    color: red;
}

//综上,占位符%什么时候使用?看是否需要保留基类%btn

(6.3 Sass的混合宏

混合宏@mixin可以定义一个要复用的代码块——混合宏,@include调用混合宏。
应对特殊情况,比如设置border,兼容各浏览器需要加浏览器前缀,且border的值我们希望是参数形式传入设置,那么,有“混合宏的参数”,参数可以是1-n个,数量不限制,参数匹配规则与js类似,也可以带默认值。

@mixin border_mixin($myBorder){
    border: $myBorder;
    -webkit-border: $myBorder;
    -moz-border: $myBorder;
}
@mixin width_mixin($width:20px){
    width: $width;
}
#nav{
    color: red;
    @include border_mixin(1px solid red);
}
.btn{
    @include border_mixin(2px solid blue)
}
//编译后:
#nav{
    color: red;
    border: 1px solid red;
    -webkit-border: 1px solid red;
    -moz-border: 1px solid red;
}

7. 判断语句@if、@else

类似js的if、else if、else的规则。

@isScroll ($boolean:flase){
    @if $boolean{
        overflow: scroll;
    } 
    @else {
        overflow: hidden;
    }
}
.box{
    height: 200px;
    @include isScroll(true)
}

8. @for循环

同类似js的for规则,很适合网格样式使用。2种写法:through和to。

to表示不包含end,through包含end@for $i from [start] to [end]
// 1 to 3 =>1,2
@for $i from [start] through [end]
// 1 through 3 => 1,2,3

9. @while循环

只要while后边的判断是true就会一直执行,适用于>n等情况。

$num: 3;
@while $num > 0 {
    .box_#{$num}{
        height: 20px;
    }
    $num: $num - 1
}
// .box_3,2,1

10. @each循环

写法:@each $el in [list]。什么时候用呢?

//比如10张不同背景图
$list: img1, img2, img3;
@each $name in $list{
    .#{$name}{
        background: url("images/#{$name}.png");
    }
}
//可以结合@mixin混入、@extend继承

四 webpack中的sass-loader做什么的

sass-loader是帮助webpack打包sass文件,把scss转换为标准的css书写格式。先把文件内的文本格式转换为常见css格式,并支持相应的优化和扩展;然后css-loader根据各文件依赖关系,整合成一段css,然后给style-loader去挂载到页面的head。