如何让 scss 代码可复用?三种复用方式分别用在何处?下方是一段自定义大小的样例 👇

$height: 15px !default;
$width: 18px !default;

@mixin size($list...) {
  @if length($list) == 0 {
    height: $height;
    width: $width;
  } @else if length($list) == 1 {
    height: $list;
    width: $list;
  } @else if length($list) == 2 {
    height: nth($list, 1);
    width: nth($list, 2);
  } @else {
    @debug "Too many parameters";
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

1、继承和占位符

两者都是通过@extend来引用。

1.1 继承

一个已经存在的 css 样式类,可以被其他样式类继承。

例如,实现以下 css 样式:

.btn,
.btn--primary,
.btn--info {
  border: 1px solid blue;
}

.btn--primary {
  color: black;
}

.btn--info {
  color: gray;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

scss 中可以这样写,显然,这种写法便于维护和阅读!

.btn {
  border: 1px solid blue;
}

.btn--primary {
  color: black;
  @extend .btn;
}

.btn--info {
  color: gray;
  @extend .btn;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

1.2 占位符

顾名思义,如果不被extend引用,它是不会被编译,也就是:不会占用 css 文件大小。这是和继承最大区别。

scss 代码如下:

%btn {
  border: 1px solid blue;
}

// 没有被extend
// 不会出现在css文件中
%test-btn {
  border: 1px solid black;
}

.btn--primary {
  color: black;
  @extend %btn;
}

.btn--info {
  color: gray;
  @extend %btn;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

编译后的 css 代码:

.btn--primary,
.btn--info {
  border: 1px solid blue;
}

.btn--primary {
  color: black;
}

.btn--info {
  color: gray;
}
1
2
3
4
5
6
7
8
9
10
11
12

2. 混合宏

scss 中的函数,通过关键字@mixin声明,@include引用。

2.1 参数设置和调用方式

无参调用 scss:

@mixin btn {
  border-radius: 3px;
}

.box {
  color: white;
  @include btn;
}
1
2
3
4
5
6
7
8

css:

.box {
  color: white;
  border-radius: 3px;
}
1
2
3
4

参数调用 scss:

$radius: 3px !default;

@mixin btn($radius: 5px) {
  // 默认是 5px
  border-radius: $radius;
}

.box {
  color: white;
  @include btn($radius); // 传入参数
}
1
2
3
4
5
6
7
8
9
10
11

css:

.box {
  color: white;
  border-radius: 3px;
}
1
2
3
4

参数过多的情况

当参数 2、3 个时候,可以通过@mixin size($width,$height)这样来调用。当参数过多,使用...符号。

scss:

$height: 15px !default;
$width: 18px !default;

@mixin size($list...) {
  @if length($list) == 0 {
    height: $height;
    width: $width;
  } @else if length($list) == 1 {
    height: $list;
    width: $list;
  } @else if length($list) == 2 {
    height: nth($list, 1);
    width: nth($list, 2);
  } @else {
    @debug "Too many parameters";
  }
}

.btn--primary {
  @include size();
}

.btn--big {
  @include size(20px, 25px);
}

.btn--square {
  @include size(18px);
}

.btn--test {
  @include size(
    1px,
    2px,
    3px,
    4px
  ); // just a test. console output "Too many parameters" what we have defined.
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

输出的 css 结果:

.btn--primary {
  height: 15px;
  width: 18px;
}

.btn--big {
  height: 20px;
  width: 25px;
}

.btn--square {
  height: 18px;
  width: 18px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

2.2 好处和不足

混合宏最大的不足:会复用代码,造成 css 冗赘(可以尝试一下下方的测试代码)。 当然,符合宏可以传递参数这点很 nice。

可以编译下方代码,观察下结果:

@mixin border-radius {
  -webkit-border-radius: 3px;
  border-radius: 3px;
}

.box {
  @include border-radius;
  margin-bottom: 5px;
}

.btn {
  @include border-radius;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

3. 版本

  • scss:3.5.6
  • ruby:2.4.4p296