为了解决 CSS 本身的缺点:
- 语法不够强大,不能够嵌套书写,难以表达样式逻辑
- 没有变量和逻辑上的复用机制,难以维护
诞生了一系列的 CSS 预处理器 Sass, Stylus, Less。
Sass从第三代开始,放弃了缩进式风格,并且完全向下兼容普通的CSS代码,这一代的Sass也被称为Scss。
文档:
- 中文文档:https://www.sass.hk
- 英文文档:https://sass-lang.com/documentation
- CSS转Scss:https://www.sass.hk/css2sass
- Scss转CSS:https://www.sassmeister.com
Sass版本
Sass有三个版本Dart Sass、libsass和Ruby Sass:
- Dart Sass,用Dart语言写的sass实现,于2016年11月1日发布alpha版本,版本1.23.0之后完全支持模块化机制
- libSass也就是俗称的node-sass,用c/c++实现的sass版本,使用非常广泛。node-sass是绑定了 libsass的nodejs库,可以极快的将.scss 文件编译为.css文件
- Ruby Sass,是最初的Sass实现,但是2019年3月26日被停止了,以后也不会再支持,使用者需要迁移到别的实现上。
语法嵌套规则
选择器嵌套
css中重复写选择器是非常恼人的。尤其是html结构嵌套非常深的时候,scss的选择器嵌套可以避免重复输入父选择器,可以有效的提高开发效率,减少样式覆盖可能造成的异常问题。这也是我们最常用的功能。
这个是正常的css结构
.container {
width: 1200px;
margin: 0 auto;
}
.container .header .img {
width: 100px;
height: 60px;
}
在 scss中只需要这么写:
.container {
width: 1200px;
margin: 0 auto;
.header {
.img {
width: 100px;
height: 60px;
}
}
}
属性嵌套
有些css属性遵循相同的命名空间 (相同的开头),比如font-family
,font-size
,font-weight
都以font
作为属性的命名空间。为了便于管理这样的属性,也为了避免重复输入。
.container {
font: {
family: fantasy;
size: 30em;
weight: bold;
}
}
命名空间也可以包含自己的属性值
.container {
color: red {
adjust: fantasy;
}
}
父选择器&
在嵌套 css 规则时,有时会需要使用嵌套外层的父选择器,例如,当给某个元素设定 hover
样式时,可以用&
代表嵌套规则外层的父选择器,scss在编译时会把&
替换成父选择器名。
案例里面的&
表示的就是父级a
选择器
.container {
a {
color: #333;
&:hover {
text-decoration: underline;
color: #f00;
}
}
}
转化成css
.container a {
color:#333;
}
.container a:hover {
text-decoration:underline;
color:#F00;
}
变量
使用
原生css中的变量,使用--变量名:变量值
定义,var(--变量名)
进行使用。
:root {
--color: #F00;
}
p {
color: var(--color);
}
scss中的变量,以美元符号$
开头,赋值方法与 css 属性的写法一样。
$color:#F00;
p {
color: $color;
}
变量作用域
- 变量作用域分为全局变量域和局部变量域:
- 全局变量:声明在最外层的变量,可在任何地方使用;
- 局部变量:嵌套规则内定义的变量只能在嵌套规则内使用。
将局部变量转换为全局变量可以添加!global
声明。
$color: red;
.container {
$height: 500px;
$font-size: 16px !global;
font-size: $font-size;
color: $color;
height: $height;
}
.footer {
/**$font-size使用!global 申明成全局变量了*/
font-size: $font-size;
}
数据类型
scss 支持 7 种主要的数据类型:
- 数字,
1rem、2vh、13、 10px
; - 字符串,分有引号字符串与无引号字符串,
"foo"、 'bar'、baz
; - 颜色,
blue, #04a3f9, rgba(255,0,0,0.5)
; - 布尔型,
true
和false
; - 空值,
null
是其类型的唯一值。表示缺少值,通常由函数返回以表示缺少结果; - 数组 (
list
),用空格或逗号作分隔符,1.5em 1em 0 2em,Helvetica,Arial,sans-serif
; maps
, 相当于JavaScript
的object
,(key1: value1, key2: value2)
;
语句
流程控制
sass中流程控制包含四类,也是我们在js中常见的@if、@for、@each、@while
。
@if
@if
语法和js类似,基本格式是@if...@else if...@else
。
@for
for
在条件范围内重复操作,这个指令包含两种格式:
@for $var from <start> through <end>
;@for $var from <start> to <end>
。
两者区别在于 through
与 to
的含义:
- 使用
through
时,条件范围包含<start>
与<end>
的值; - 使用
to
时条件范围只包含<start>
的值不包含<end>
的值; $var
可以是任何变量,比如$i
,<start>
和<end>
必须是整数值。
@for $i from 1 to 3 {
#loading span:nth-child(#{$i}) {
width: 20 * ($i - 1) + px;
}
}
@each
@each
指令的格式是@each $var in $list
, $var
可以是任何变量名,比如$length
或者$name
,而$list
是一连串的值,也就是值列表。
$color-list:red green blue turquoise darkmagenta;
@each $color in $color-list {
$index: index($color-list, $color);
.p#{$index - 1} {
background-color: $color;
}
}
@while
@while
指令循环输出直到表达式返回结果为 false
。这样可以实现比@for
更复杂的循环。
$column:12;
@while $column>0 {
.col-sm-#{$column} {
width: $column / 12 * 100%;
}
$column:$column - 1;
}
@import
@import
算是一个比较简易的模块系统。拓展了@import
的功能,允许其导入 scss或 文件。被导入的文件将合并编译到同一个 文件中,被导入的文件中所包含的变量或者混合指令 (mixin
) 都可以在导入的文件中使用。
common.scss
$color:red;
index.scss
@import "common.scss";
.container {
border-color: $color;
}
以下情况下,@import
仅作为普通的语句,不会导入文件:
- 文件拓展名是
.css
; - 文件名以
http://
开头; - 文件名是
url()
; @import
包含媒体查询。
允许同时导入多个文件,例如同时导入 rounded-corners
与text-shadow
两个文件,不用再单独写个import
引入。
@import "rounded-corners", "text-shadow";
@media 媒体查询增强
中,@media
指令与 中用法一样,只是增加了一点额外的功能,允许在规则中嵌套。如果@media
嵌套在 规则内,编译时,@media
将被编译到文件的最外层,包含嵌套的父选择器。这个让 @media
方便不少,不需要重复写选择器,也不会打乱 的书写流程。
.sidebar {
width: 300px;
@media screen and (orientation: landscape) {
width: 500px;
.item {
height: auto;
}
}
}
@mixin
混合指令(Mixin
)用于定义可重复使用的样式。混合指令可以包含所有的规则,绝大部分 规则,甚至可以通过参数功能引入变量,输出多样化的样式。
注意:函数命名和变量命名规则一致。
@mixin mixin-name() {
/* css 声明 */
}
// 使用
@include mixin-name;
// 定义一个区块基本的样式
@mixin block {
width: 96%;
margin-left: 2%;
border-radius: 8px;
border: 1px #f6f6f6 solid;
}
// 使用混入
.container {
.block {
@include block;
}
}
编译为
.container .block {
width: 96%;
margin-left: 2%;
border-radius: 8px;
border: 1px #f6f6f6 solid;
}
摘抄整理自 前端达人
Last modified on 2023-10-04