Sass
文章目录
简介
在学习Sass之前,我们先来介绍一下什么是CSS预处理器;因为Sass就是众多CSS预处理器中的其中一种
CSS预处理器
因为CSS是一门描述性的语言,只能一行一行得解释HTML标签的样式,并不能使用函数,变量,循环等方式来操作标签样式;而CSS预处理器就是用来解决这个问题的方法,使用预处理器来写CSS,让代码具有更加简洁、适应性更强、可读性更佳、更易于代码
;
目前最常见的CSS预处理器:
- Sass
- Less
- Stylus
Sass的两种格式
Sass有两种语言格式:
- Sass
- Scss
Sass:
Sass格式,是Sass的“旧版本语法”;这种语法格式,不使用大括号“{}”和分号" ; ",而是使用严格的缩进式语法规则来书写,也就是类似Ruby语言的写法
Scss:
Scss格式,是Sass的“新版本语法”;这种语法格式,使用大括号“{}”和分号" ; ",并不使用严格的缩进式语法规则来书写,也就是类似CSS书写的格式
安装
Sass的安装,我们使用npm方式(下载node.js就能使用npm)进行;执行命令:
npm install -g sass
等待下载完毕后,执行:
sass
若出现帮助文档,证明安装成功
使用方法
单文件编译
创建test.scss
文件,并写入内容(Sass样式):
body {
background-color: aqua;
h1 {
color: red;
}
}
然后在该文件的所在目录下,打开cmd
命令终端,使用命令:
sass 目标编译文件名 编译后生成文件名
于是可以看到,Sass自动编译生成了test.css
文件
但这种方法每次改动.scss
文件都需要手动执行命令编译一次,不是特别方便
单文件监听编译
可以监听单个文件的改动,一改动就编译;命令:
sass --watch 目标编译文件名:编译后生成文件名
随后只要文件中的内容一改变,Sass就能监听到,自动重新编译该文件
但这种方法只能监听单个文件,也不是特别方便
多文件监听编译
可以监听一个文件夹中的多个文件,一改动就编译;命令:
sass --watch 目标编译文件目录:编译后生成文件目录
随后,该文件夹中的scss文件一改动,Sass就能监听到,自动重新编译改动文件
设置文件不编译
有些文件我们不想Sass进行编译生成CSS文件,可以将它们命名为_文件名.文件后缀
的形式,Sass就不会编译它们了;一般情况下,我们将那些被其他Sass文件导入使用的工具Sass文件设置不被编译
例:使用命令sass --watch sass:css
监听编译,发现_main.scss
不会被Sass编译出CSS文件
输出格式设置
输出文件格式有四种:
nested
嵌套输出expanded
展开输出(默认)compact
紧凑输出compressed
压缩输出
但我使用时,只有expanded
展开输出和compressed
压缩输出能使用
命令:
// 这里以多文件监听为例:
npm --watch /*监听目标目录*/:/*编译生成文件目录*/ --style /*输出格式*/
例:
// 展开格式:适合开发时使用
sass --watch sass:css --style expanded
// 压缩格式:适合项目打包上线时最后一次编译
sass --watch sass:css --style compressed
其他人的nested
和compact
模式(我没法使用):
基础格式
选择器嵌套
Sass支持选择器嵌套写法,更加清晰且直观地查看与管理选择器的父子关系
Sass父类选择器
&就表示直接调用父选择器,你可以把&理解为它是&外面的所有父选择器
属性嵌套
属性名称前都具有相同的字符前缀时(eg:background,font…),可使用属性嵌套方法来简写;
- 注意:font: {},冒号后与花括号中间需有空格进行隔开
占位符选择器%
占位选择器可以用于定义一套样式,给多个选择器使用;使用方法:
- 使用
%样式库名称 {样式...}
的方式定义样式库- 在需要使用该样式库的选择器中,使用
@extend %样式库名称;
来引用样式
代码注释
支持标准的 Css 的注释语法,单行注释 //
与多行注释 /* */
;注释在 .scss
中的规则:
- 单行注释
//
不会解析编译到.css
文件中 - 若选择的输出格式是
compressed
,则所有的注释信息都不会解析编译到.css
文件中 - 在多行注释 中添加
!
,即使选择的输出格式是compressed
,也会解析编译到.css
文件中,此方法主要用于文件的版权声明 - 多行注释中可以使用插值语法
#{变量名}
,来引用变量
extended输出模式下:
compressed输出模式下:
文件导入
使用@import
进行文件导入
导入.scss
文件
导入方式:
// .scss文件后缀可加可不加
@import 'main.scss'
@import 'main'
- 编写
main.scss
文件
$author:'Bokey';
html {
background-color: #fff;
}
- 编写
test.scss
,并使用sass --watch sass:css
进行编译
为了使导入的类不经过编译再生成css
文件,可以将它们命名为_文件名
的形式,就不会经过Sass编译了
附:
- 工具文件名字虽为
_main.scss
,但导入时可以使用@import 'main'
或者@import '_main'
- 导入文件同样也可以写入选择器中,写入选择器后,导入的文件中的所有变量将只适用于该选择器:
导入普通的.css
文件
以下几种方式,只会将文件作为普通的 css 语句进行引入
- 文件拓展名为 .css
- 文件名以 http:// 或 https:// 开头
- 文件由 url() 的形式引入
- @import 包含 媒体查询
@import 'main.css';
@import 'http://puji.design/main.css';
@import url(main);
@import 'landscape' screen and (orientation: landscape);
注:采用 @import ‘main.css’ 这种形式引入文件,编译后,文件地址将为计算机的绝对地址,这样的引入形式慎用,建议采用 @import url(main) 的方式
变量
使用符号 $
定义变量,变量名称可自己命名,赋值方法与CSS相同。如:$myColor: red;
注意:
变量的定义与使用需有先后顺序,即先定义变量,然后再使用变量,书写的顺序则是将定义变量写在前面,使用变量写在后面
变量命名规则
- 用符号 “$” 开头,后面跟随变量名称
- 变量名称需使用字母开头,中间可使用字母、数字、中横线(连接符)、下划线
- 支持大/小写字母
- 多个单词的连接,可以使用横线 “-“、下划线 “_” 或驼峰式的命名形式
注意:
如果同样的单词,分别采用横线与下划线来连接,此名称相当于是同一个名称(eg:
my-color === my_color
),在解析时,会采用最后一个声明的变量来解析;因此在命名的时候建议统一使用一个符号;
!default变量默认值
可以使用 !default
为每个变量设置一个默认值,如果该变量没有被重新定义过,则会将该变量解析为默认值,如果已经有过定义,则会取其以定义过的值
作用域
和Java一样,变量的作用域取决于变量被定义在哪里
局部变量:
body {
/* 局部变量,只在body选择器中有用 */
$local: red;
h1 {
color: $local;
}
}
全局变量:
/* 全局变量,全局有效 */
$global: red;
body {
color: $global;
}
!global
强制声明全局变量:
body {
/* 强制$local变量为全局变量,注意:!global 要写在 ; 里面 */
$local: red !global;
h1 {
color: $local;
}
}
html {
color: $local;
}
数据类型
Scss 支持以下几种主要的数据类型:
- 字符串( 有引号或无引号的字符串 ):”foo”, ‘bar’, baz, …
- 数字:1, 2.5, 18px, 30%, 9a, …
- 颜色:blue, #00ff00, rgba(0, 0, 0, .1)
- 布尔型:true, false
- 空值:null
- 数组 (list), 用逗号或空格分割:1em 2em 2.5em 或 Helvetica, Arial, sans-serif, …
- maps,相当于 JavaScript 中的 object:key1: value1, key2: value2, …
判断数据类型的方式: type-of($value)
数组
通过空格或半角逗号分割的一系列的值,数组中还可以包含子数组,如下方的 “ l i s t 2 ”和“ list2” 和 “ list2”和“list3″,当数组被编译为 css 时,圆括号不会被添加
$list1: 1px 2px 3px 4px; //一维数字
$list2: 1px 2px, 3px 4px; //二维数字
$list3: (1px 2px) (3px 4px); //二维数字
// 得到数组中的某个值
nth( $/*数组名*/, /*第几个值*/);
映射Maps
Maps 必须被圆括号包裹,可以映射任何键值对
$map: (
key1: value1,
key2: value2,
key3: value3
);
相关函数:
map-get(map,key)
- 得到映射中对应 key 的值,如没有对应的 key,则返回 null 值map-has-key(map,key)
- 判断 map 是否有对应的 key,存在返回 true,否则返回 falsemap-keys(map)
- 返回 map 中所有的 key 组成的队列map-merge(map1,map2)
- 合并两个 map 形成一个新的 map 类型,即将 map2 添加到 map1的尾部mep-remove(map,key...)
- 移除 map 中的 keys,多个 key 使用逗号隔开map-values(map)
- 返回 map 中所有的 value 并生成一个队列
运算符
相等运算符
所有数据类型都支持等号运算符,等于使用 ==
表示,不等于使用 !=
表示
关系运算符
关系运算符只支持数字,使用的符号分别是大于号 >
,小于号 <
,大于等于号 >=
与小于等于号 <=
,返回值 true
或 false
,主要应用于条件判断
布尔运算
布尔运算符包含三种形式,分别是与 and
、 或or
、 非not
数字运算符
数字运算符包含加 +
,减 -
,乘 *
,除 /
与取模 %
,取模即是两个数字相除取余数
基本用法:
// 纯数字相加
$plus1: 30 + 30; //60
$plus2: 30px + 30; //60px
$plus3: 30% + 30%; //60%
$plus4: 30px + 30pt; //70px
$plus5: 30px + 30pt + 30pc; //550px
//纯数字相减
$minus1: 60 - 30; //30
$minus2: 60px - 30; //30px
$minus3: 60% - 30%; //30%
$minus4: 60px - 30pt; //20px
$minus5: 60px - 30pt - 30pc; //-460px
//纯数字相乘
$multipl1: 60 * 30; //1800
$multipl2: 60px * 30; //1800px
$multipl3: 60% * 30; //1800%
$multipl4: 60px * 30 * 30; //54000px
//纯数字相除
$division1: (60 / 30); //2
$division2: (60px / 30); //2px
$division3: (60% / 30%); //2
$division4: (60px / 30pt); //1.5
$division5: (60px / 30 / 30); //0.06667px
//纯数字取模
$modulo1: 60 % 9; //6
$modulo2: 60px % 9; //6px
$modulo3: 60% % 9%; //6%
$modulo4: 60px % 9pt; //0px
$modulo5: 60px % 9 % 5; //1px
混合用法:
// 数字,字符串相加
$plus1: a + b; //ab
$plus2: "a" + "b"; //"ab"
$plus3: 'a' + 'b'; //"ab"
$plus4: 'a' + b; //"ab"
$plus5: a + 'b'; //ab
$plus6: 'a' + 1; //"a1"
$plus7: "1" + a; //"1a"
// 数字,字符串相减
$minus1: a - b; //a-b
$minus2: "a" - "b"; //"a"-"b"
$minus3: 'a' - 'b'; //"a"-"b"
$minus4: 'a' - b; //"a"-b
$minus5: a - 'b'; //a-"b"
$minus6: 'a' - 1; //"a"-1
$minus7: "1" - a; //"1"-a
$minus8: 1 - "a"; //1-"a"
// 数字无法与纯字符串相乘,除,取模!
- 字符串相加时,如果前面一个值带引号,计算的结果同样带引号,反之
- 数字与字符串混合相加时,第一位有引号或第一位是数字,且后最后一位有引号时,结果必定有引号
除法的使用:
如果直接在值之间使用 /
,不可被视为除法运算,会被视为CSS的分隔符,仅当一下三种情况时才会以除法进行运算:
- 如果值或值的一部分是变量或函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
// scss 代码编辑
$width: 100px;
div {
width: $width / 2; //使用变量
z-index: round($number: 10) / 2; //使用函数
height: (500px / 2); //使用圆括号
margin-left: 5px + 8/2; //使用了+表达式
}
// 编译后的 css
div {
width: 50px;
z-index: 5;
height: 250px;
margin-left: 9px;
}
规则总结:
- 运算符号与值之间建议使用空格隔开
- 数字可以只声明其中一个符号或单位,计算的结果将以声明的符号或单位进行编译,声明单位或符号时,建议在第一个数字上进行声明
- 当不同符号且符号之间不可以进行换算时,无法计算出结果,如 20px + 10%无计算,
px
+pt
则可进行计算 - 当不同单位进行运算,结果会显示以运算公式开头的数字设置的单位
- 在乘法运算时,只需为一个数字声明单位,为多个数字声明同样或不同的单位都会报错
- 在除法运算时,如需声明单位,单位建议标注在除号前面的值
- 书写公式时,建议将所有公式都使用圆括号包
字符串运算
使用加号 +
可连接字符串,如字符串前面带引号后面不带,编译出的结果会带引号,反之
// scss 代码编辑
.container {
content: "Foo" + bar;
font-family: sans- + "serif";
}
// 编译后的 css
.container {
content: "Foobar";
font-family: sans-serif;
}
插值语句
插值语句 #{...}
,常用于变量值的提取
混入@mixin
混合指令用于定义可重复使用的样式。混合指令可以包含所有的 Css 规则与绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式;相当于为自己定义一个CSS函数
基础写法:
若混入中有选择器:
带参数的混入:
- 可以指定参数传参
- 可以为参数设置默认值
数组形式的参数:
总结:
- 混合指令 ( @mixin ) 是可以重复使用的一组 Css 声明
- 有助于减少重复代码,只需声明一次就可以在文件中反复引用
- 包含所有 Css 规则以及绝大部分 Sass 规则,甚至通过参数引入变量
- 使用参数时,建议加上默认值
继承@extend
在不同的元素具有完全相同的样式与 CSS 属性时,可以使用继承指令实现,继承指令 @extend
;顾名思义,继承一些样式
继承可以搭配占位符选择器 %
使用,来定义一套样式,用于其他选择器共用
语句
条件语句@if,@else
在Sass中可以使用@if、@if-else 、@else if 来进行条件判断,用法和JS相同
循环语句
在Sass中可以使用@for、@while 、@each 来进行循环操作
@for的用法不同于JS,Sass中的for有两种格式:
- @for $i from n through m 表示变量i 的范围是[n, m]
- @for $i from n to m 表示变量i 的范围是[n, m)
@while的用法于JS相同
@each 用法是 $i in list, list 是一连串的值,也就是值列表
自定义函数
在Sass中可以使用@function编写函数;虽然mixin
已经足够强大,但有时我们不需要指定属性名而只是单纯的想要返回属性值,此时可以通过自定义函数,它和mixin
类似,不同点在于它必须有返回值,使用@return
返回
在Vue中构建Sass
在Vue项目中使用命令:
// 项目中安装Sass
npm install -D -S sass
// 安装Sass-loader,Sass编译器
npm install -D sass-loader
然后在使用时,在.vue
文件标签中设置编译语言为scss<style lang='scss'>
<style lang='scss'>
/* Sass代码... */
</style>
若可以成功使用Scss语法,就可以进行整个 Vue + Sass 的项目构建了:
- 在
assets
文件夹中创建scss
文件夹,用于存放项目中的全局Sass设置;
base.scss
- 用于存放项目的基础样式iconfont.scss
- 用于存放项目的字体样式相关的配置index.scss
- Sass全局设置的入口文件,用于引入reset
,base
,iconfont
文件mixin.scss
- 用于存放Sass的全局混入(函数)reset
- 用于存放对一些固定标签样式的重新设置(如:ul
标签的list-style:none;
)variable.scss
- 用于存放Sass的全局变量
base.scss
:
// 项目基础样式
body, html {
background-color: $color-background;
color: $color-text;
}
iconfont.scss
:
// 对字体图标的设置...
index.scss
:
// Sass入口文件
@import 'reset';
@import 'base';
@import 'iconfont';
mixin.scss
:
// Sass函数(混入)...
reset.scss
:
// 对一些固定标签样式的重设...
ul {
list-style: none; // 去除列表小圆点
}
a {
text-decoration: none; // 去除a标签下划线
color: $color-text; // 更改a标签的默认颜色(蓝色)为全局变量的 $color-text
}
variable.scss
:
// Sass全局变量
/* 基本颜色 */
$color-background: #424242;
$color-text: #fff;
/* 基本字体大小 */
$font-size-large: 30px;
$font-size-medium: 20px;
$font-size-small: 10px;
- 在
main.js
文件中引入Sass的入口文件
// 引入Sass的入口文件
import '@/assets/scss/index.scss';
- 在
vue.config.js
中,引入Sass全局变量和全局混入(函数)
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 添加css配置,全局引入Sass全局变量和Sass全局函数
css: {
loaderOptions: {
// sass-loader
scss: {
additionalData: `
@import '@/assets/scss/variable.scss';
@import '@/assets/scss/mixin.scss';
`
}
}
}
})