选择器
嵌套
.container {
.header {
.title {
font-size: 20px;
font-weight: bold;
}
}
}
连接父选择器
.item {
background-color: red;
&:hover {
background-color: blue;
}
}
属性嵌套
.title {
font: {
size: 50px;
weight: bold;
}
}
编译结果:
.title {
font-size: 50px;
font-weight: bold;
}
注释
多行注释
/**
这是scss多行注释
*/
单行注释
// 这是scss单行注释
不会编译到最终css文件,因为在css文件中不存在单行注释
变量
分隔符
$color_primary: yellow;
$color-primary: red;
p {
color: $color_primary; // red
}
在scss中,_
和-
是同一个符号,也就是$color-primary
和$color_primary
代表同一个变量,所以在使用scss时,最好只选用其中一种作为分隔符
作用域
注意:scss变量作用域和css变量作用域规则是不一致,scss变量作用域规则是按照选择器嵌套关系决定的,而css变量作用域是按照Dom元素嵌套关系决定的
局部作用域
header {
$color-primary: yellow;
p {
color: $color-primary;
}
}
全局作用域
$color-primary: yellow;
header {
p {
color: $color-primary;
}
}
!global
加上!global
关键字代表设置为全局变量
header {
$color-primary: red !global;
}
p {
color: $color-primary;
}
值类型
// 颜色类型
$color: red;
// 单位像素
$size: 16px;
// 数组
$padding: 12px 15px;
// rgb颜色
$background: rgb(255, 0, 0);
// 数组
$font-family: "Arial", "Helvetica";
// null
$content: null;
// 布尔值
$boolean: true;
// Map
$colorMap: (
"red": #ff0000,
"green": #00ff00,
"blue": #0000ff,
);
p {
color: map-get($colorMap, "red");
}
默认值
$color-primary: yellow !default;
$color-primary: red;
p {
color: $color-primary; // red
}
!default
代表变量默认值,也可以理解为替补值
在编译到!default
定义的变量时,会先校验是否已经存在当前名称的变量,如果存在就忽略这个定义,不存在就定义当前变量
@import
规则
要使用scss的@import
语法导入时,需要按照特定规则书写
@import "./theme.scss"
@import "./theme.css"
@import "./theme"
// index.scss
@import "./theme";
p {
color: $color;
}
// theme.scss
$color: red;
.title {
color: $color;
}
编译结果:
.title {
color: red;
}
p {
color: red;
}
在使用scss的@import
导入时,编译结果是将被导入文件的内容导入到当前文件,进行合并输出
注意:如果不按照上述规则导入,将会编译为css导入
// index.scss
@import url("./theme.scss");
编译结果:
// index.scss
@import url("./theme.scss");
scss就不会处理这种导入语句,会编译成css的导入语句
局部文件
scss会编译所有的scss文件,并且生成对应的css文件,如果项目中某个文件只负责声明全局变量,那么也会生成应该空的css文件,这显然是不合理的
如果在文件命名时以_
开头,比如_theme.scss
文件,那么就不会单独生成theme.css
文件了
嵌套
header {
@import "./_theme.scss";
color: $color;
}
@import
语法还可以写在选择器内部,但是并不常用
@use
@use
和@import
的编码规范是一样的,在使用时,必须按照固定规则
@use "./uses/variable.scss";
不能出现url
关键字
@use
导出和esModel模块化
导出差不多,有命名空间、首次执行等
重复执行
@import
在重复导入同一个模块时,会重复执行模块的内容,也就会导出多个样式表
@use
模块只会在第一次导入时执行,并且缓存导出的变量、混入特性,后续的导出语句只会再导出这些特性的引用
内容覆盖
在两个模块中定义相同的变量名称
使用@import
导入两个文件,按照执行顺序,后面定义的变量会覆盖前面相同名称的变量
而@use
是根据命名空间访问变量,所以不会覆盖
模块
模块名称
@use "./uses/_variable.scss" as variable;
.button {
&--primary {
color: variable.$color-primary;
}
}
在导入其他模块时,需要通过模块名称访问器内部暴露的变量、混入等,所以as variable
就是给被导入的模块设置模块名称,如果在导入时,不特意去给模块命名,编译器也会按照模块的名称自动加上模块导出名称
@use "./uses/_variable.scss"
// 等同于
@use "./uses/_variable.scss" as variable;
as
是给模块取别名
模块名称唯一
在一个文件内中模块名称必须保持唯一
@use "./uses/_variable1.scss" as variable;
@use "./uses/_variable2.scss" as variable;
虽然导入的是不同的文件,但是因为设置模块名称重复,这里会报错
取消模块空间
@use "./uses/_var.scss" as *;
button {
color: $color-primary;
}
as *
就是把模块中的特性全部平铺到导入文件中,一般使用入口文件在合并导出中
// _index.scss
@use "./_var.scss" as *;
@use "./_reset.scss" as *;
@use "./_theme.scss" as *;
这样在其他文件使用这些基础特性时,只需要导入_index.scss
就可以了
@use "./uses/_index.scss" as base;
注意:无法在引入_index.scss
时,使用到_var.scss
、_reset.scss
、_theme.scss
导出的特性,如果需要使用,则需要使用@forward
关键字
私有成员
在引入模块时,会自动引入变量、混入等特性,但有时定义特性只想在当前空间使用,不对外暴露,在定义需在可以名称以_
或-
开头
// _var.scss
$-color-primary: red;
// index.scss
@use "./uses/_var.scss";
button {
color: var.$-color-primary; // 报错,访问不到私有变量
}
修改默认值
// _var.scss
$color-primary: red !default;
// index.scss
@use "./uses/_var.scss" as * with($color-primary: yellow);
button {
color: $color-primary;
}
with
中的代码会预先加载到模块代码之前,也就是提前定义模块变量,当遇到!default
关键字时,判断之前已经定义了变量,就不会采用默认变量
模块之间访问
模块之间是相互独立的空间,就算import.scss
在上面导入了_var.scss
,在_mixin.scss
还是需要使用导入_var.scss
才能使用特性
@forward
上面讲过@use
也能实现合并,但是不能实现转发,如果需要转发必须
// _index.scss
@use "./_reset.scss";
@use "./_var.scss";
@use "./_theme.scss";
// 转发语法
$color-primary: var.$color-primary;
// use.scss
@use "./uses/_index.scss" as base;
header {
color: base.$color-primary;
}
显然如果对每个特性都要单独写转发语句,这是得不偿失的, @forward
可以实现特性合并转发一体
// _index.scss
@forward "./_reset.scss";
@forward "./_var.scss";
@forward "./_theme.scss";
// use.scss
@use "./uses/_index.scss" as base;
header {
color: base.$color-primary;
}
合并文件使用特性
@forward "./_var.scss";
$copy-color-primary: var.$color-primary; // 报错,访问不到
@forward
只是用于合并转发,如果要在合并文件访问模块变量,必须使用@use
@use "./_var.scss";
@forward "./_var.scss";
$copy-color-primary: var.$color-primary;
@use和@forward同时使用
定义with
必须只有一种语法,并且必须放在上面
@use "./_var.scss" with (
$color-primary: green
);
@forward "./_var.scss";
导出别名
当多个模块出现同名变量时会产生报错
@forward "./_base.scss";
@forward "./_var.scss";
这里会产生报错,我们可以给不同的模块特性添加不同的前缀
// _index.scss
@forward "./_base.scss" as base-*;
@forward "./_var.scss" as var-*;
// use.scss
@use "./uses/_index.scss" as *;
header {
color: $var-color-primary;
}
限制转发特性
只想转发模块中部分特性
@forward "./_var.scss" show $color-primary;
也可以使用排除语法
// _index.scss
@forward "./_var.scss" hide $color-primary;
注意:如果设置了导出别名,那么在限制导出变量时,也要更具导出别名限制
@forward "./_var.scss" as var-* show $color-primary;
原理
// _var.scss
$color-primary: #409eff;
$color-success: #67c23a;
$color-warning: #e6a23c;
// _index.scss
@forward "./_var.scss" as var-* show $var-color-primary;
使用@use
来实现
@use "./_var.scss" as var;
$var-color-primary: var.$color-primary;
默认值
注意:虽然使用了别名,但是因为with
是将内容嵌入到原文件,所以变量还是要使用原来的变量名称
如需在use.scss
设置默认值,那么必须在_index.scss
文件中使用!default
关键字定义默认值
还需注意的是,在use.scss
默认的名称要加上别名前缀
mixin混入
无参数
@mixin title-style {
font-size: 16px;
font-weight: bold;
text-align: center;
}
.title {
@include title-style;
}
带参数
@mixin button-style($color, $hover-color) {
color: $color;
&:hover {
color: $hover-color;
}
}
button {
@include button-style(red, blue);
}
指定名称传参
@mixin padding($top, $right, $bottom, $left) {
padding-top: $top;
padding-right: $right;
padding-bottom: $bottom;
padding-left: $left;
}
header {
@include padding($top: 10px, $right: 20px, $bottom: 30px, $left: 40px);
}
参数默认值
@mixin padding($top: 0, $right: 0, $bottom: 0, $left: 0) {
padding-top: $top;
padding-right: $right;
padding-bottom: $bottom;
padding-left: $left;
}
header {
@include padding(20px);
}
剩余参数
@mixin linear-gradient($direction, $colors...) {
color: nth($list: $colors, $n: 2);
background-image: linear-gradient($direction, $colors);
}
$colors: red, blue, yellow;
header {
@include linear-gradient(to right, $colors...);
}
extend继承
.button {
display: inline-block;
padding: 12px 25px;
cursor: pointer;
color: white;
border-radius: 5px;
}
.buuton--info {
@extend .button;
background-color: red;
}
.button--success {
@extend .button;
background-color: green;
}
占位符%
.button
在这里只是当作基础样式,并不需要编译至css代码中,所以可以使用占位符
%button {
display: inline-block;
padding: 12px 25px;
cursor: pointer;
color: white;
border-radius: 5px;
}
.buuton--info {
@extend %button;
background-color: red;
}
.button--success {
@extend %button;
background-color: green;
}
这样在最后的css编译结果中就没有.button
样式表了
继承和混入的区别
- 混入会把样式合并到当前
@include
位置上,但继承是建立在不影响当下情况下,创建一个样式表 - 继承通过扩展选择器来实现样式的复用,而混入则通过定义可重用的代码块并按照需要引入来实现
运算符
相等运算
@mixin button-size($size) {
@if $size == small {
padding: 5px 10px;
} @else if $size == medium {
padding: 10px 20px;
} @else if $size == large {
padding: 15px 30px;
}
}
button {
@include button-size(medium);
}
比较运算
@mixin text-line($line) {
@if ($line == 1) {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} @else {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
}
}
.titel {
@include text-line(2);
}
逻辑运算
and
@mixin button-style($size, $type) {
@if ($size == "small" and $type == "info") {
background-color: red;
}
}
button {
@include button-style("small", "info");
}
or
@mixin button-style($is-loading, $is-disabled) {
@if ($is-disabled or $is-loading) {
color: #ccc;
}
}
button {
@include button-style(true, false);
}
not
@mixin button-style($isdisabled) {
@if (not $isdisabled) {
background-color: red;
}
}
button {
@include button-style(false);
}
算术运算
运算限制
%
不能和其他单位一起运算- 纯数字和带有单位的值进行运算时,结果是转为对应的单位
除法
因为在css中/
被当作分隔符,所以在使用/
进行运算时,需要区分使用
- 运算表达式被括号包裹
- 属于算术表达式的一部分
- 操作符两边的值是变量或者来自函数的返回值
$num: 1.5;
.title {
font: (12px / 1.5) "微软雅黑";
font: 12px / 1.5 + 1 "微软雅黑";
font: 12px / $num "微软雅黑";
}
字符串运算
单位拼接
.title {
font-size: 10 + px;
}
字符串拼接
.title {
content: "hello" + " " + "world";
}
插值运算
插值运算允许你在选择器、属性名或者属性值中插入动态内容,通常是变量或者其他表达式的值。插值使用 #{}
语法来进行。
选择器
$namespace: "el";
.#{$namespace}-button {
}
属性名
$font: "font";
.title {
#{$font}-size: 16px;
#{$font}-weight: bold;
}
注释
$data: "2024-01-01";
/** #{$data} */
属性值
$size: "16px";
$line: 32px;
.title {
font-size: #{$size};
line-height: #{$line};
}
注意:
-
在属性值中使用插值时,如果值本身是一个有效的 CSS 值,则不需要使用
#{}
$size: 16px; .title { font-size: $size; // 16px }
-
在插入字符串值时,会自动转为非字符串值
$size: "16px"; .title { font-size: #{$size}; // 16px }
-
插入的值不会再参加后续运算
$size: "16px";
.title {
font-size: #{$size} + 15px; // 16px + 15px;
}
常用函数
颜色相关的函数
- lighten() 和 darken(): 改变颜色的亮度。
- saturate() 和 desaturate(): 改变颜色的饱和度。
- adjust-hue(): 改变颜色的色调角度。
- rgb(), rgba(), hsl(), hsla(): 创建颜色值。
- transparentize(): 使颜色透明化。
- opacity(): 获取颜色的不透明度。
- color(): 获取颜色的 RGB 或 HSL 值。
- alpha(): 获取颜色的 Alpha 值。
- mix(): 创建两种颜色的混合色。
- complement(): 计算颜色的补色。
- invert(): 计算颜色的反色。
数学相关的函数
- percentage(): 将数值转换为百分比。
- round(): 四舍五入一个数字。
- ceil(): 向上取整。
- floor(): 向下取整。
- abs(): 返回一个数的绝对值。
- min(), max(): 返回一组数中的最小值或最大值。
- pi(): 返回圆周率 π 的值。
字符串相关的函数
- str-length(): 返回字符串长度。
- str-insert(): 在指定位置插入字符串。
- str-index(): 返回子字符串的位置。
- str-lower(): 将字符串转换为小写。
- str-upper(): 将字符串转换为大写。
- str-trim(): 删除字符串首尾的空白字符。
- str-quote(): 添加引号到字符串两端。
- str-replace(): 替换字符串中的子字符串。
- escape(): 对字符串进行 URL 编码。
列表相关的函数
- length(): 返回列表的长度。
- nth(): 获取列表中的某个元素。
- append(): 向列表末尾添加元素。
- prepend(): 向列表开头添加元素。
- join(): 连接两个列表。
- index(): 返回列表中元素的位置。
- sort(): 对列表排序。
- unique(): 移除列表中的重复项。
其他有用的函数
- unit(): 获取一个数值的单位。
- unitless(): 检查一个数值是否无单位。
- type-of(): 获取一个值的数据类型。
- inspect(): 输出一个值的调试信息。
- call(): 调用其他函数。
- if(): 执行条件判断。
流程控制
if
header {
color: if(theme == "dark", "white", "black");
}
@if
$theme-list: "light", "dark";
@mixin theme-title-style($theme-type) {
@if ($theme-type == nth($theme-list, 1)) {
.title {
background-color: red;
}
} @else if ($theme-type == nth($theme-list, 2)) {
.title {
background-color: blue;
}
}
}
@include theme-title-style("dark");
@for
@for $i from 1 through 3 {
.item-#{$i} {
width: 100px * $i;
}
}
@for $i from 1 to 3 {
.item-#{$i} {
width: 100px * $i;
}
}
to和through差异
through
关键字时,循环范围是**[start,end]**
to
关键字时,循环范围是**[start,end)**
@each
用于遍历list和map类型的数据
$button-size-map: (
"small": (
font-size: 12px,
),
"medium": (
font-size: 14px,
),
"large": (
font-size: 16px,
),
);
@each $type, $value in $button-size-map {
.button-#{$type} {
@each $prop, $val in $value {
#{$prop}: $val;
}
}
}
@while
@mixin create-cols($max-cols: 12) {
$current-cols: 1;
@while ($current-cols <= $max-cols) {
.col-#{$current-cols} {
width: $current-cols / $max-cols * 100 * 1%;
}
$current-cols: $current-cols + 1;
}
}
@include create-cols(12);
@function
@function px2pw($value) {
@return $value / 750 * 100 + vw;
}
header {
height: px2pw(100);
font-size: px2pw(750);
}
函数和混入的调用方式一样,同样拥有参数、默认参数、按照参数名称传值、剩余参数等
函数和混入的区别
- 混入是封装公共的操作,生成结果是一系列的样式表
- 函数是处理某些计算操作,返回结果是一个数据的值
@at-root
用于将嵌套规则提升到当前作用域的根级别
疑难问题
Sass 和 Scss 区别
Sass和Scss是两种不同阶段提出的语法规则,也就是两种不同的预处理语言,就和Less和Sass区别是一样的
在先项目中使用Sass或Scss编译器任意一种,都可以编译两种语言
比如:在项目中安装Sass编译器
pnpm install sass -D
也可以在编译Scss语法
<style lang="scss"></style>
list类型
在scss中以空格或逗号分隔的多个值是list类型数据
$theme-list: "light", "dark";
引号与字符串
header {
content: top == "top"; // true
}
top和*"top"*都是scss的字符串类型