如何让 scss 代码可复用?三种复用方式分别用在何处?
下方是一段自定义大小的样例 👇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $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"; } }
|
(本文使用的是: scss v3.5.6 和 ruby v2.4.4)
继承
在 scss 中,一个样式类,可以被其他样式类直接继承,从而减少重复代码的编写。
例如,在 css 中,代码如下:
1 2 3 4 5 6 7 8 9 10 11
| .btn, .btn--primary, .btn--info { border: 1px solid blue; } .btn--primary { color: black; } .btn--info { color: gray; }
|
在 scss 中,代码如下:
1 2 3 4 5 6 7 8 9 10 11
| .btn { border: 1px solid blue; } .btn--primary { color: black; @extend .btn; } .btn--info { color: gray; @extend .btn; }
|
对比 css 的代码,编写出的 scss 代码语义更强:.btn
是基础样式类,.btn--primary
和.btn--info
是扩展样式类。
占位符
顾名思义,如果不被引用,它是不会被编译到 css 文件中的。这是和继承最大区别。
scss 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| %btn { border: 1px solid blue; }
%test-btn { border: 1px solid black; } .btn--primary { color: black; @extend %btn; } .btn--info { color: gray; @extend %btn; }
|
编译后的 css 代码,并没有占位符%test-btn
的样式代码。编译后的 css 如下:
1 2 3 4 5 6 7 8 9 10
| .btn--primary, .btn--info { border: 1px solid blue; } .btn--primary { color: black; } .btn--info { color: gray; }
|
混合宏
它是 scss 中的函数,通过关键字@mixin
声明,@include
引用。
无参调用
scss:
1 2 3 4 5 6 7
| @mixin btn { border-radius: 3px; } .box { color: white; @include btn; }
|
编译后的 css:
1 2 3 4
| .box { color: white; border-radius: 3px; }
|
参数调用
scss:
1 2 3 4 5 6 7 8 9
| $radius: 3px !default; @mixin btn($radius: 5px) { border-radius: $radius; } .box { color: white; @include btn($radius); }
|
编译后的 css:
1 2 3 4
| .box { color: white; border-radius: 3px; }
|
...
参数运算符
scss:
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
| $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 ); }
|
编译后的 css:
1 2 3 4 5 6 7 8 9 10 11 12
| .btn--primary { height: 15px; width: 18px; } .btn--big { height: 20px; width: 25px; } .btn--square { height: 18px; width: 18px; }
|
优缺点
优点是可以传递参数,更加灵活。缺点是编译后的 css 代码可能存在“冗赘”,例如下方代码:
1 2 3 4 5 6 7 8 9 10 11
| @mixin border-radius { -webkit-border-radius: 3px; border-radius: 3px; } .box { @include border-radius; margin-bottom: 5px; } .btn { @include border-radius; }
|
在这种灵活性不高的场景下,“占位符”是更好的选择。
思考:编程语言特性 & 预处理
除了文中所述的 3 种样式复用的手段,scss 更引入了变量声明、循环、条件判断、函数(混合宏)、模块等编程语言才有的概念,使得开发者在编写样式代码的时候也可以编写复杂逻辑。
但 scss 本身还是预处理器(浏览器无法直接解析),一段短小精悍的代码,经过预处理后的 css 代码可能非常庞大。比如在 scss 中编写经典的“24 栅栏布局”代码,一个从 0-23 的循环即可,寥寥几行。但是最终生成的 css 一行都不会少。
因此,不光要利用 scss 的编程语言特性来简化样式代码,还要考虑编译后的 css 文件的大小。毕竟网络传输开销辣么大!