本文不做 SASS 系统的讲解,仅解释几个知识点和如何系统的使用 SASS 进行开发。
推荐一个不错的学习资料 《CSS预处理器SASS从入门到高级进阶》
知识点
拓展名
SASS 有两种拓展名:sass
和 scss
。在 3.x 之前的版本中使用 sass
,在 3.x 及之后的版本中使用 scss
$ 符
当 $
用在选择器名称时,代指父级选择器名称,并且会用父级选择器替代 $
,类似 C 语言中的宏。因此可以有下面两种最常见用法:
.header {
background-color: white;
// 下面的选择器等同于:.header:hover
$:hover {
background-color: purple;
}
// 下面的选择器等同于:.header-title
$-title {
color: black;
}
}
对象化描述
对于 font-*
这种设置字体相关属性的属性名,在 CSS 中需要一个一个的全量输入。在 SASS 中可以使用类似对象的描述方式
.header {
font: {
size: 14pt;
family: san-serif;
}
}
上面的代码编译后为:
.header {
font-size: 14pt;
font-family: san-serif;
}
所以,这种写法也是一种替换和组合。编译器会把两个属性的名称使用 -
进行连接组成最后的属性名。例如
.header {
font: {
size: 14pt;
family: san-serif;
aa: 11;
}
}
会被编译为:
.header {
font-size: 14pt;
font-family: san-serif;
font-aa: 11;
}
变量
对于变量,最重要的是:定义变量、使用变量、变量作用域。
在 SASS 中,定义和使用变量都是 $<variable_name>
。
在变量定义时要注意,多个单词连接时要统一使用 _
。SASS 在 _
和 -
的处理上有点问题。使用时不会区分两者。也就是说 aa_bb
和 aa-bb
会当成一个变量处理。但是如果定义了 aa_bb
但是没有定义 aa-bb
,这是使用 aa-bb
会报错。
所以为了避免使用时造成困扰,两个单词之前统一使用 _
。
作用域
SASS 中分为全局变量和局部变量。所有使用 {}
包裹的都是局部作用域。{}
还可以进行嵌套形成父层级和子层级。
局部作用域可以访问所有全局变量;子层级可以访问父层级变量;父层级不能使用子层级变量
$global_color: #333;
.container {
// 可访问 global_color
$first_level_color: #666;
div {
// 可访问 first_level_color 和 global_color
$second_level_color: #999;
}
}
默认值
当使用一个变量时,这个变量可能没有定义。特别是项目复杂后,不能判断变量是否一定有值,此时可以给变量定义一个默认值,如果变量没有被赋值就使用这个默认值。
// 类似 TS 中的 `??` 操作符
$theme_color: #333 !default;
.container {
background_color: $theme_color;
}
父子关系
在 SASS 中,使用嵌套来表示 CSS 中的子代选择器。
.container {
a {
color: black;
}
}
从书写上看,a
选择器是 .coantainer
选择器的直接子代。但这种书写方式的实际效果指的是所有子孙后代。因为上面的代码会被编译为 .container a {}
而不是 .container > a {}
代码复用
SASS 中有三种方式实现代码复用:@include
和 @mixin
,@extend
和 [prefix]%<base_name> {}
,@import
和 <name>.scss
@include
和其他两种方式最大的不同是可以传参。
@mixin Test {
background_color: #333;
}
@mixin TestP(condition) {
@if(condition > 1) {
background_color: #666;
} @else {
background_color: #999;
}
}
.container {
@include Test;
}
.footer {
@include TestP(10);
}
@extend
和 @include
的不同是,@extend
可以降低代码文件大小;@include
会复制代码,增加代码体积。
@import
使用 @import
可以实现代码复用。比如有一个 variable.scss
定义了所有用到的变量。其他文件可以直接引入这个文件实现共享并统一变量命名。
// header.scss
@import 'variable'
.....
但是,variable.scss 也会被编译成 css,逻辑上讲,variable.scss 没有必要被编译为 css。为了解决这个问题,可以把 variable.scss
命名为 _variable.scss
,这时 _variable.scss
不会被编译为 css,也可以正常被其他文件引用(@import 'variable'
)。
CSS 中的 @import
因为 CSS 中也有 @import,为了区分只有写成 @import 'name'
或者 @import 'name.scss'
时才会引入 scss,否则就当普通 CSS 语句处理。
工程建议
项目组织
建议使用如下组织方式:
| <global_color>.scss
| <global_variable>.scss
| <mixin>.scss
| <module_related_selector_list>.scss
| <entry_point_assemble>.scss
这样做的好处是,可以实现模块化管理,条理清晰。同时通过使用多个 <global_color>
实现多个主题效果
子代选择器
<html>
<header></header>
<body>
<div class="A">
<p>this is section A</p>
<div><span>subtitle</span></div>
</div>
<div class="C">this is conrtol</div>
</body>
</html>
如果想要实现 A 组控件效果根据 C 组件的状态变化。那么可以创建多个和 C 相关的选择器
.A {
color: black
}
.C_visible {
p, div {
color: white;
}
}
.C_invisible {
p, div {
color: purple
}
}
使用如下代码就能实现 C 显示/隐藏时,A 组发生对应变化
// visible
$(".A").removeClass("C_invisible").addClass("C_visible")
// invisible
$(".A").removeClass("C_visible").addClass("C_invisible")