# CSS 预处理器

  • 基于 CSS 的另一种语言
  • 通过工具编译成 CSS
  • 添加了很多 CSS 不具备的特性
  • 能提升 CSS 文件的组织

常见的是less(基于node,是用js写的编译比较快)、sass、scss(sass的一个新版本)

# css预处理器的特性

  • 嵌套 反应层级和约束
  • 变量和计算 减少重复代码
  • Extend 和 Mixin 代码片段
  • 循环 适用于复杂有规律的样式
  • import CSS 文件模块化

# 实现嵌套

在less中实现:

body{
    padding:0;
    margin:0;
}

.wrapper{
    background:white;

    .nav{
        font-size: 12px;
    }
    .content{
        font-size: 14px;
        // &代表平级的关系
        &:hover{
            background:red;
        }
    }
}

编译的结果:

body {
  padding: 0;
  margin: 0;
}
.wrapper {
  background: white;
}
.wrapper .nav {
  font-size: 12px;
}
.wrapper .content {
  font-size: 14px;
}
.wrapper .content:hover {
  background: red;
}

使用scss实现相同的效果:

body{
    padding:0;
    margin:0;
}

.wrapper{
    background:white;

    .nav{
        font-size: 12px;
    }
    .content{
        font-size: 14px;
        &:hover{
            background:red;
        }
    }
}

# 变量

两者唯一不同的是定义变量使用的符号不一样。 在less中:


// 定义变量
@fontSize: 12px; // 需要带单位
@bgColor: red;

body{
    padding:0;
    margin:0;
}

.wrapper{
    // less的函数lighten,将颜色变浅
    background:lighten(@bgColor, 40%);
    .nav{
        font-size: @fontSize;
    }
    .content{
        font-size: @fontSize + 2px;
        &:hover{
            background:@bgColor;
        }
    }
}

scss中:


$fontSize: 12px;
$bgColor: red;

body{
    padding:0;
    margin:0;
}
.wrapper{
    background:lighten($bgColor, 40%);
    .nav{
        font-size: $fontSize;
    }
    .content{
        font-size: $fontSize + 2px;
        &:hover{
            background:red;
        }
    }
}

# CSS 代码复用

之前我们通过定义class然后在html中进行复用,添加两个类。 在预处理器中,可以使用mixin解决,就相当于定义函数

在less中:

.block(@fontSize){
    font-size: @fontSize;
    border: 1px solid #ccc;
    border-radius: 4px;
}
.wrapper{
    background:lighten(@bgColor, 40%);

    .nav{
        .block(@fontSize);
    }
    .content{
        // 注意这里直接加2px
        .block(@fontSize + 2px);
        &:hover{
            background:red;
        }
    }
}
// 也可以直接写成类
.box {
  color: blue
}
// 最后编译的结果.box是存在的
.box1 {
  .box()
  line-height: 2em;
}
.box2 {
  .box()
  line-height: 3em;
}

编译后的结果:

.wrapper {
  background: #ffcccc;
}
.wrapper .nav {
  font-size: 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.wrapper .content {
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.wrapper .content:hover {
  background: red;
}

scss中使用:需要两个关键字 @mixin 跟 @include

@mixin block($fontSize){
    font-size: $fontSize;
    border: 1px solid #ccc;
    border-radius: 4px;
}
.wrapper{
    background:lighten($bgColor, 40%);

    .nav{
        @include block($fontSize);
    }
    .content{
        @include block($fontSize + 2px);
        &:hover{
            background:red;
        }
    }
}

# extend

在上面我们使用mixin进行将代码复用,但是我们会发现如果样式相同还是在代码中有很多重复:

.wrapper .nav {
  font-size: 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.wrapper .content {
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
/* 如果我们自己写 */
.wrapper .nav
.wrapper .content {
  border: 1px solid #ccc;
  border-radius: 4px;
}
.wrapper .nav {
  font-size: 12px;
}
.wrapper .content {
  font-size: 14px;
}

可以使用extend解决这个问题,在less中使用:

.block{
    font-size: @fontSize;
    border: 1px solid #ccc;
    border-radius: 4px;
}
.wrapper{
    background:lighten(@bgColor, 40%);
    .nav:extend(.block){
        color: #333;
    }
    .content{
        &:extend(.block);
        &:hover{
            background:red;
        }
    }
}

编译后的代码:

.block,
.wrapper .nav,
.wrapper .content {
  font-size: 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.wrapper {
  background: #ffcccc;
}
.wrapper .nav {
  color: #333;
}
.wrapper .content:hover {
  background: red;
}

在scss中使用:是使用关键字@extend进行复用

.block{
    font-size: $fontSize;
    border: 1px solid #ccc;
    border-radius: 4px;
}
.wrapper{
    background:lighten($bgColor, 40%);
    .nav{
        @extend .block;
        color: #333;
    }
    .content{
        @extend .block;
        &:hover{
            background:red;
        }
    }
}

# 循环 loop

适用于有规律的逻辑实现 比如我们想要实现这样的效果: 我们将一行分为十二列,总共1000px宽,这样每一列占十二分之一

.col-12 {
  width: 1000px;
}
.col-11 {
  width: 916.66666667px;
}
.col-10 {
  width: 833.33333333px;
}
.col-9 {
  width: 750px;
}
.col-8 {
  width: 666.66666667px;
}
.col-7 {
  width: 583.33333333px;
}
.col-6 {
  width: 500px;
}
.col-5 {
  width: 416.66666667px;
}
.col-4 {
  width: 333.33333333px;
}
.col-3 {
  width: 250px;
}
.col-2 {
  width: 166.66666667px;
}
.col-1 {
  width: 83.33333333px;
}

我们用less实现:

.gen-col(@n) when (@n > 0) {
  .gen-col(@n - 1);
  .col-@{n}{
      width: 1000px/12*@n;
  }
}
.gen-col(12)

使用scss实现:sass是支持循环的

@mixin gen-col($n) {
  @if $n > 0 {
    @include gen-col($n - 1);
    .col-#{$n} {
      width: 1000px / 12 * $n
    }
  }
}
@include gen-col(12)

// 使用 for 循环
@for $i from 1 through 12 {
  .col-#{$i} {
    width: 1000px / 12 * $i
  }
}

# 模块化 import

预处理器中的变量可以跨文件使用的,在less中: 模块的简单的用法:

@import "./variable";
@import "./module1";
@import "./module2";

// variable
@themeColor: blue;
@fontSize: 14px;

// module1
.module1{
    .box{
        font-size:@fontSize + 2px;
        color:@themeColor;
    }
    .tips{
        font-size:@fontSize;
        color:lighten(@themeColor, 40%);
    }
}
// module2
.module2{
    .box{
        font-size:@fontSize + 4px;
        color:@themeColor;
    }
    .tips{
        font-size:@fontSize + 2px;
        color:lighten(@themeColor, 20%);
    }
}

编译后的结果:

.module1 .box {
  font-size: 16px;
  color: blue;
}
.module1 .tips {
  font-size: 14px;
  color: #ccccff;
}
.module2 .box {
  font-size: 18px;
  color: blue;
}
.module2 .tips {
  font-size: 16px;
  color: #6666ff;
}

在scss中模块化的用法:

@import "./variable";
@import "./module1";
@import "./module2";
// variable
$themeColor: blue;
$fontSize: 14px;
// module1
.module1{
    .box{
        font-size:$fontSize + 2px;
        color:$themeColor;
    }
    .tips{
        font-size:$fontSize;
        color:lighten($themeColor, 40%);
    }
}
// module2
.module2{
    .box{
        font-size:$fontSize + 4px;
        color:$themeColor;
    }
    .tips{
        font-size:$fontSize + 2px;
        color:lighten($themeColor, 20%);
    }
}

# CSS 预处理器框架

  • sass - Compass(兼容性的封装、获取图片宽高等等、)
  • Less - Lesshat / EST
  • 提供现成的mixin
  • 类似JS类库 封装常用功能 下面的代码是使用est 库的一个例子:
@import "est/all";
@support-ie-version: 7;
@use-autoprefixer: false;
.global-reset();
.box{
    .inline-block();
    .opacity(60);
    height: 100px;
    background: green;
    margin:10px;
}
.left{
    float:left;
    .clearfix();
}
.row{
    .make-row();
    .col{
        .make-column(1/4);
        background:red;
        height: 100px;
    }
}
.my-triangle{
    margin:100px;
}
.my-triangle::after{
    content: ' ';
    .triangle(top left, 100px, red, side);
}

# CSS 面试题

# 预处理器的作用

  • 帮助更好的组织css代码
  • 提高代码的复用率
  • 提升可维护性

# 预处理器的能力

  • 嵌套 反应层级和约束
  • 变量和计算 减少重复代码
  • Extend 和 Mixin 代码片段
  • 循环 适用于复杂有规律的样式
  • import CSS 文件模块化

# 预处理器的优缺点

  • 优点:提高代码复用率和可维护性
  • 缺点:需要引入编译过程 有学习成本

评 论:

更新: 11/21/2020, 7:00:56 PM