一. SASS 编译基础
1. SASS 与 CSS 的关系
SASS(Syntactically Awesome Style Sheets)是 CSS 的预处理器和增强版,提供了:
-
变量、嵌套、混合等高级功能
-
更简洁的语法结构
-
模块化开发支持
但浏览器无法直接解析 SASS 文件,必须编译为标准 CSS 才能被浏览器识别。
2. 传统编译方式(Gulp 方案)
在早期前端工程化中,常用 Gulp + gulp-sass 构建编译流程:
// 1. 引入所需工具
const { src, dest, watch, series } = require('gulp') // Gulp 核心方法
const sass = require('gulp-sass')(require('sass')); // Sass 编译器(Dart Sass)
// 2. 定义编译任务
function buildStyles() {
return src('index.scss') // 读取源文件
.pipe(sass()) // 编译 SASS -> CSS
.pipe(dest('css')) // 输出到 css 目录
}
// 3. 定义文件监听任务
function watchTask() {
watch(['index.scss'], buildStyles) // 监听文件变化时自动重新编译
}
// 4. 配置默认任务
exports.default = series( //series按顺序执行多个任务
buildStyles, // 首次执行编译
watchTask // 启动监听
)
工作流程解析:
-
文件输入:
src()
读取项目根目录的index.scss
-
编译转换:
sass()
调用 Dart Sass 编译器进行转换 -
文件输出:
dest()
将生成的 CSS 写入css
目录 -
持续监听:
watch()
监测文件变动自动触发重新编译
3. 现代框架
当前主流框架已内置 SASS 支持,无需手动配置构建流程
二. 变量的使用
1. 属性值的复用(修改和维护更加便利)
在 CSS 开发过程中,某些属性值(如颜色、间距、边框样式等)会被频繁重复使用。如果直接写死在样式中,一旦需要修改,就需要逐个查找替换,效率低且容易出错。SASS 提供了变量(Variables)机制,可以将这些常用值统一定义并复用,使样式表更易于维护和扩展。
示例说明:
// theme colors
$primary: #326dee !default;
$secondary: #1ac886 !default;
$error: #d32752 !default;
$info: #f6c31c !default;
// spacing
$base-padding: 0.75rem;
$base-margin: 0.75rem;
// borders
$base-border-thickness: 1px;
$base-border-radius: 20px;
以上代码定义了一系列 SASS 变量,用于存储颜色、间距、边框等样式值。这些变量可以在多个选择器中被引用,实现样式的统一控制。
例如:
h1 {
color: $primary; // 使用主题主色
margin-bottom: $base-margin; // 使用基础外边距
}
通过这种方式,只需要修改变量的值,即可全局更新所有使用该变量的样式,极大提升了开发效率与可维护性。
2. 变量的定义方式
SASS 变量以 $
符号开头,后接变量名和值:
$variable-name: value;
-
基本语法:
$primary-color: #326dee;
-
支持多种数据类型:
- 颜色:
#326dee
,rgb(255, 0, 0)
- 数字:
16
,1.5
- 字符串:
"hello"
,sans-serif
- 布尔值:
true
,false
- 列表:
10px 20px 30px 40px
- map(键值对):
(key1: value1, key2: value2)
- 颜色:
3. 变量的命名规范
良好的变量命名有助于团队协作和后期维护。建议遵循以下规范:
- 语义清晰:变量名应能清楚表达其用途,如
$base-padding
表示基础内边距。 - 统一风格:推荐使用小写字母加连字符(kebab-case),如
$theme-color-primary
。 - 避免缩写过度:除非是通用缩写(如 btn、nav),否则不建议使用模糊缩写。
- 按用途分类命名:
- 颜色类:
$color-primary
,$color-error
- 间距类:
$spacing-small
,$spacing-base
- 边框类:
$border-radius
,$border-width
- 颜色类:
4. 默认值与 !default
标志
SASS 支持为变量设置默认值,使用 !default
关键字。只有当该变量尚未被定义时才会赋值。
$primary: #326dee !default;
此特性常用于组件库或主题系统中,允许用户自定义变量而不影响默认逻辑。
5. 变量的作用域
SASS 变量具有作用域概念:
- 全局变量:在任何嵌套层级之外定义的变量,默认为全局。
- 局部变量:在某个选择器或 mixin 内部定义的变量,仅在该作用域内有效。
$global-var: red;
.my-class {
$local-var: blue;
color: $local-var;
}
三. Partials & @import
1. Partials(部分文件)
-
用途:解决代码过长过乱的问题,通过拆分代码为多个文件实现模块化开发
-
命名规则:在文件名前加下划线
_
(如:_variables.scss
) -
特点:
-
不会被单独编译成 CSS 文件
-
作为代码模块供其他文件引用
-
-
优势:
-
提高代码可维护性
-
便于团队协作开发
-
实现功能模块的分离
-
2. @import 指令
-
作用:导入其他 SASS 文件
-
使用方式:
@import 'filename'; // 不需要带下划线或扩展名
-
特点:
-
可以省略部分文件的
_
前缀和.scss
扩展名 -
支持嵌套导入(在规则内导入)
-
导入顺序影响变量和混合器的可用性
-
-
最佳实践:
-
建议在文件开头集中导入依赖
-
基础文件(变量、混合器等)优先导入
-
3. 组合使用
典型项目结构示例:
sass/
│
├── _variables.scss # 全局变量
├── _mixins.scss # 混合器
├── _reset.scss # 样式重置
├── _buttons.scss # 按钮组件
├── _forms.scss # 表单组件
│
└── main.scss # 主入口文件
main.scss 内容示例:
// 1. 基础模块
@import 'reset';
@import 'variables';
@import 'mixins';
// 2. 组件模块
@import 'buttons';
@import 'forms';
// 3. 页面模块
@import 'pages/home';
@import 'pages/contact';
注意:新版Sass推荐使用@use
替代@import
,但传统项目仍广泛使用此方式
4. Sass 文件导入顺序
核心原则
- 依赖优先:被依赖的文件必须优先导入
- 分层管理:从抽象到具体,从基础到组件
- 变量先行:所有变量和函数需在最顶层导入
// 1. 核心依赖层(必须最先导入)
@import 'variables'; // 全局变量(颜色、间距、字体等)
@import 'functions'; // Sass函数工具
@import 'mixins'; // 混合宏
// 2. 基础样式层
@import 'reset'; // 样式重置/normalize
@import 'base'; // 基础HTML元素样式
// 3. 主题/颜色系统
@import 'colors'; // 颜色方案(可覆盖variables中的颜色)
// 4. 组件层(按组件复杂度排序)
@import 'buttons'; // 按钮组件(依赖variables中的颜色变量)
@import 'forms'; // 表单组件
@import 'card'; // 卡片组件
@import 'navbar'; // 导航栏
// 5. 工具类(最后导入)
@import 'utilities'; // 工具类(margin/padding等)
四. 嵌套规则
1.基本示例:
SASS 代码
.card {
display: block;
padding: $base-padding;
border: $base-border-thickness solid #ddd;
box-shadow: $base-box-shadow;
.card-title {
font-size: $base-font-size;
padding-bottom: $base-padding;
font-weight: bold;
}
.card-body {
font-size: $base-font-size;
a {
text-decoration: underline;
}
}
}
编译后的 CSS
.card {
display: block;
padding: 0.75rem;
border: 1px solid #ddd;
box-shadow: 1px 3px 5px rgba(0,0,0,0.1);
}
.card .card-title {
font-size: 1rem;
padding-bottom: 0.75rem;
font-weight: bold;
}
.card .card-body {
font-size: 1rem;
}
.card .card-body a {
text-decoration: underline;
}
2.核心特性:
父选择器引用 (&)
.btn {
&-primary { background: blue; }
&:hover { opacity: 0.8; }
.sidebar & { width: 100%; }
}
属性嵌套
.element {
border: {
width: 1px;
style: solid;
color: #eee;
}
font: {
family: Arial;
size: 14px;
}
}
媒体查询嵌套
.container {
width: 100%;
@media (min-width: 768px) {
width: 750px;
}
}
注意 :控制嵌套深度(3-4层为佳),过度嵌套会生成冗长的 CSS,影响性能
五. SASS中数学的运用
1.基本数学运算
SASS 支持标准的数学运算符:
$base-size: 16px;
.container {
width: $base-size * 5; // 乘法 → 80px
padding: $base-size / 2; // 除法 → 8px
margin: $base-size + 10px; // 加法 → 26px
height: $base-size - 4px; // 减法 → 12px
}
特别注意除法运算
需要使用 math.div()
或添加括号:
@use 'sass:math';
.item {
// 新推荐方式
width: math.div(100px, 2); // → 50px
// 传统方式(需括号)
height: (100px / 2); // → 50px
}
2.math 模块函数
常用数学函数
@use 'sass:math';
@debug math.div(10, 3); // 3.333...
@debug math.$pi; // 3.1415926536
@debug math.floor(2.6); // 2(向下取整)
@debug math.ceil(2.1); // 3(向上取整)
@debug math.round(2.6); // 3(四舍五入)
@debug math.max(1px, 20px, 15px, 12px); // 20px
@debug math.min(1px, 20px, 15px, 12px); // 1px
数学常量
@debug math.$e; // 2.7182818285(自然对数底数)
@debug math.$pi; // 3.1415926536(圆周率)
3.实际应用示例
字体缩放系统
$base-font-size: 1rem;
$font-size-sm: $base-font-size * 0.75; // 0.75rem
$font-size-lg: $base-font-size * 1.5; // 1.5rem
$font-size-xl: $base-font-size * 2; // 2rem
$font-size-xxl: $base-font-size * 3; // 3rem
.text {
&-small { font-size: $font-size-sm; }
&-large { font-size: $font-size-lg; }
}
响应式间距计算
$spacing-unit: 8px;
.container {
padding: $spacing-unit * 2; // 16px
margin: math.div($spacing-unit, 2); // 4px
@media (min-width: 768px) {
padding: $spacing-unit * 3; // 24px
}
}
圆形元素计算
@use 'sass:math';
$circle-size: 100px;
.avatar {
width: $circle-size;
height: $circle-size;
border-radius: math.div($circle-size, 2); // 50px
// 或使用百分比:
// border-radius: 50%;
}
单位运算规则
- ** 兼容单位运算**:
@debug 10px + 20px; // 30px
@debug 1in + 6px; // 102px(1in = 96px)
- 相对单位计算:
@debug 10px * 3rem; // 30px*rem(无效单位会报错)
- 单位转换:
$width: 960px;
@debug math.div($width, 16px) * 1rem; // 60rem
六. Maps
1.Map 基本概念
Map 是 SASS 中的一种数据结构,用于存储键值对集合,使用圆括号 ()
定义:
// 定义 Map
$colors: (
"primary": #326dee,
"secondary": #1ac886,
"error": #d32752,
"info": #f6c31c
);
2.Map 基本操作
定义 Map
// 空 Map
$empty-map: ();
// 带值的 Map
$font-weights: (
"regular": 400,
"medium": 500,
"bold": 700
);
访问 Map 值
.test-btn {
background: map-get($colors, "purple"); // 使用 map-get 获取值
color: map-get($colors, "white");
}
检查键是否存在
@debug map-has-key($colors, "secondary"); // true
@debug map-has-key($colors, "tertiary"); // false
3.Map 常用函数
获取值
$primary-color: map-get($colors, "primary");
合并 Map
$new-colors: map-merge($colors, ("pink": #ffc0cb));
移除键值对
$filtered-colors: map-remove($colors, "primary", "info");
获取所有键/值
$all-keys: map-keys($colors); // 返回所有键的列表
$all-values: map-values($colors); // 返回所有值的列表
4.Map 实用技巧
多层嵌套 Map
$theme: (
"colors": (
"primary": #326dee,
"secondary": #1ac886
),
"spacing": (
"sm": 8px,
"md": 16px
)
);
// 获取嵌套值
$primary: map-get(map-get($theme, "colors"), "primary");
遍历 Map
/**
* 使用 @each 指令遍历 $colors map 生成一系列颜色类
*
* 实现原理:
* 1. 遍历 $colors 这个 Sass Map 数据结构
* 2. 每次迭代获取当前项的键名($name)和对应的值($color)
* 3. 动态生成 CSS 类选择器和颜色规则
*
* 生成结果示例:
* .text-primary { color: #326dee; }
* .text-secondary { color: #1ac886; }
* ...(其他颜色类)
*
* 使用说明:
* 在HTML中可以直接使用生成的类名,如:
* <p class="text-primary">这段文字将显示主色</p>
* <p class="text-error">这段文字将显示错误色</p>
*
* 参数说明:
* $colors - 包含颜色键值对的Sass Map变量
* $name - 当前迭代的颜色名称(如"primary"、"secondary"等)
* $color - 当前迭代的颜色值(十六进制、RGB等格式)
*/
@each $name, $color in $colors {
/**
* 生成以.text-开头的CSS类选择器
* 使用插值语法 #{$name} 动态拼接类名
*/
.text-#{$name} {
/* 设置文字颜色为当前迭代的颜色值 */
color: $color;
/**
* 可以在此扩展其他相关样式
* 例如:
* &:hover { opacity: 0.8; }
* 会生成 .text-primary:hover 等规则
*/
}
}
默认值处理
$color: map-get($colors, "tertiary") or #ccc; // 如果不存在则返回 #ccc
5.Map 与其它特性结合
结合函数使用
@function color($key) {
@return map-get($colors, $key);
}
.button {
background: color("primary");
}
结合 @content 使用
/**
* 定义一个名为 color-variants 的 mixin
* 用于根据颜色映射表($map)生成一系列颜色变体类
*
* 特性:
* 1. 支持动态生成BEM风格的修饰符类
* 2. 通过@content支持内容注入
* 3. 自动遍历颜色映射表生成样式
*
* @param {map} $map - 颜色映射表,格式为(key: value)
*/
@mixin color-variants($map) {
/**
* 使用@each遍历颜色映射表
* $name - 当前颜色名称(如"primary")
* $color - 当前颜色值(如#326dee)
*/
@each $name, $color in $map {
/**
* 生成修饰符选择器
* &表示父选择器,生成类似.text--primary的类名
*/
&--#{$name} {
// 设置文字颜色为当前颜色值
color: $color;
/**
* @content指令允许在mixin调用处注入额外样式
* 此处注入的样式会应用到每个颜色变体
*/
@content;
}
}
}
/**
* 使用示例:
* 为.text元素生成一系列颜色变体类
* 同时为所有变体添加font-weight: bold样式
*/
.text {
@include color-variants($colors) {
/**
* 通过@content注入的样式
* 这里设置的font-weight会应用到所有颜色变体
*/
font-weight: bold;
/**
* 可以继续添加其他共用样式
* 例如:
* text-transform: uppercase;
*/
}
}
/**
* 编译结果示例:
* .text--primary {
* color: #326dee;
* font-weight: bold;
* }
* .text--secondary {
* color: #1ac886;
* font-weight: bold;
* }
* ...其他颜色变体
*/
6.注意事项
- Map 不可变性:所有 map 函数都返回新 map,不修改原始 map
$new-map: map-remove($colors, "primary"); // 原 $colors 不变
- 键的类型:键可以是任何 SASS 数据类型(包括 map)
$complex-map: (
1px: "pixel",
"red": #ff0000,
(1,2): "tuple"
);
七. 循环
1. @each
循环
基本语法
@each $var in $list {
// 循环体
}
特点
-
用于遍历列表(list)或映射(map)中的每一项
-
示例中遍历了
$colors
映射(map)的键值对 -
可以同时获取键和值:
@each $key, $value in $map
示例代码分析
@each $key, $val in $colors {
// 为每个颜色生成.text-和.bg-类
.text-#{$key} {
color: $val;
}
.bg-#{$key} {
background-color: $val;
}
}
2. @for
循环
基本语法
@for $var from <start> through <end> {
// 循环体
}
// 或
@for $var from <start> to <end> {
// 循环体
}
特点
-
用于按数字范围循环
-
through
包含结束值,to
不包含结束值 -
常用于生成一系列相似的样式规则
示例代码分析
// 生成颜色的浅色变体
@for $i from 1 through 9 {
.text-#{$key}-light-#{$i} {
// mix() 函数将颜色与白色混合,创建浅色变体
// 参数1: 白色 (要混合的基础颜色)
// 参数2: 原始颜色 ($val)
// 参数3: 混合比例 (i*10 = 10%-90%)
// 比例越高,白色占比越大,颜色越浅
color: mix(white, $val, $i * 10);
}
}
// 生成颜色的深色变体
@for $i from 1 through 9 {
.text-#{$key}-dark-#{$i} {
// mix() 函数将颜色与黑色混合,创建深色变体
// 参数1: 黑色 (要混合的基础颜色)
// 参数2: 原始颜色 ($val)
// 参数3: 混合比例 (i*10 = 10%-90%)
// 比例越高,黑色占比越大,颜色越深
color: mix(black, $val, $i * 10);
}
}
关于 mix()
函数的补充说明:
-
函数语法:
mix($color1, $color2, $weight: 50%)
-
参数解释:
-
$color1
:第一种要混合的颜色 -
$color2
:第二种要混合的颜色 -
$weight
:可选参数,表示第一种颜色的权重比例(默认50%)
-
-
在代码中的应用:
-
浅色变体:将原色与白色混合,
$i * 10
从10%到90%递增 -
深色变体:将原色与黑色混合,
$i * 10
从10%到90%递增
-
-
数学关系:
-
当
$weight
为 0% 时,结果完全是$color2
-
当
$weight
为 100% 时,结果完全是$color1
-
当
$weight
为 50% 时,两种颜色各占一半
-
3. @each
和 @for
的区别
特性 | @each | @for |
---|---|---|
用途 | 遍历列表或映射中的元素 | 按数字范围循环 |
循环条件 | 集合中的每个元素 | 数字范围(start到end) |
获取内容 | 可以获取键和值 | 只能获取当前数字 |
典型场景 | 生成基于一组颜色/尺寸的类 | 生成有规律的序号类(如1-9) |
灵活性 | 更适合处理已知的有限集合 | 更适合处理需要计算的数字序列 |
4. 组合使用技巧
在实际项目中,@each
和 @for
经常组合使用,如示例中:
-
先用
@each
遍历颜色映射 -
然后在每个颜色循环内部,用
@for
生成该颜色的深浅变体
这种组合可以高效地生成大量有规律的CSS类,减少重复代码。
5. 实用提示
-
循环变量可以使用任意名称,但应保持语义化(如
$key
,$val
,$i
) -
在循环体内可以使用插值语法
#{$var}
动态生成类名 -
嵌套循环时要小心选择变量名,避免冲突
-
过度使用循环可能会生成大量CSS,注意控制范围
八. 条件判断(@if
)
1. 基础语法
基本结构
@if <condition> {
// 条件为真时执行的代码
}
完整结构(带 else)
@if <condition> {
// 条件为真时执行
} @else {
// 条件为假时执行
}
多条件判断
@if <condition1> {
// 条件1为真时执行
} @else if <condition2> {
// 条件2为真时执行
} @else {
// 以上条件都不满足时执行
}
2. 条件表达式
比较运算符
运算符 | 说明 | 示例 |
---|---|---|
== | 等于 | $size == 10px |
!= | 不等于 | $color != red |
< | 小于 | $width < 100 |
> | 大于 | $height > 50 |
<= | 小于等于 | $columns <= 12 |
>= | 大于等于 | $index >= 1 |
逻辑运算符
运算符 | 说明 | 示例 |
---|---|---|
and | 逻辑与 | $size > 10 and $size < 20 |
or | 逻辑或 | $color == red or $color == blue |
not | 逻辑非 | not $is-dark |
特殊运算符
运算符 | 说明 | 示例 |
---|---|---|
% | 取模运算 | $index % 2 == 0 |
+ | 字符串连接/数字相加 | $name + '-active' |
3. 常见使用场景
变量控制样式
$theme: dark;
body {
@if $theme == dark {
background: #333;
color: white;
} @else {
background: white;
color: #333;
}
}
响应式断点
@mixin respond-to($breakpoint) {
@if $breakpoint == phone {
@media (max-width: 600px) { @content; }
} @else if $breakpoint == tablet {
@media (max-width: 900px) { @content; }
} @else if $breakpoint == desktop {
@media (min-width: 901px) { @content; }
}
}
循环中的条件判断
@for $i from 1 through 12 {
.col-#{$i} {
width: percentage($i / 12);
@if $i % 3 == 0 {
border-right: none;
}
}
}
4. 实用技巧
检查变量是否存在
@if variable-exists(primary-color) {
color: $primary-color;
} @else {
color: #333;
}
检查函数是否存在
@if function-exists(calc) {
width: calc(100% - 20px);
}
检查混合宏是否存在
@if mixin-exists(box-shadow) {
@include box-shadow(0 2px 4px rgba(0,0,0,0.1));
}
5. 注意事项
-
单位敏感:
10px == 10
返回false
,因为单位不同 -
颜色比较:
red == #ff0000
返回true
,因为它们是相同颜色 -
空值判断:
@if $var { ... }
在$var
为null
或false
时为假 -
列表判断:
@if index($list, $item)
检查元素是否在列表中 -
嵌套条件:可以嵌套使用
@if
语句,但要注意可读性
6. 与循环结合示例
@each $name, $color in $theme-colors {
.btn-#{$name} {
background-color: $color;
@if lightness($color) > 50% {
color: #000; // 浅色背景用黑色文字
} @else {
color: #fff; // 深色背景用白色文字
}
}
}
九. 父选择器
1. 基础概念
什么是父选择器
-
&
符号代表父选择器的引用 -
在嵌套规则中表示外层的选择器
-
编译时会替换为父选择器的内容
基本用法示例
.btn {
&-primary {
// 编译为 .btn-primary
}
&:hover {
// 编译为 .btn:hover
}
}
2. 在示例代码中的应用分析
普通类名生成
.text-#{$key} {
color: $val;
}
// 直接生成如 .text-red 类
伪类应用
.text-hover-#{$key} {
&:hover {
color: $val;
}
}
// 编译为 .text-hover-red:hover
条件判断中的使用
@if ($val != black and $val != white) {
.text-hover-#{$key}-light-#{$i} {
&:hover {
color: mix(white, $val, $i * 10);
}
}
}
// 当条件满足时生成带伪类的变体
3. 主要功能和使用场景
生成复合选择器
.card {
&-header {
// .card-header
}
&-body {
// .card-body
}
}
添加伪类和伪元素
a {
&:hover, &:focus {
// a:hover, a:focus
}
&::before {
// a::before
}
}
添加修饰类
.btn {
// 基础按钮样式
// 这里可以添加按钮的基本样式属性
// 例如: padding, border, background-color 等
// &.active 表示同时有 btn 和 active 类的元素
// 编译结果为: .btn.active
// 用于表示按钮的激活状态
&.active {
// 激活状态的样式
// 例如: background-color: darken($primary, 10%);
}
// &[disabled] 表示带有 disabled 属性的 btn 元素
// 编译结果为: .btn[disabled]
// [disabled] 是属性选择器,匹配具有 disabled 属性的元素
// 用于表示按钮的禁用状态
&[disabled] {
// 禁用状态的样式
// 通常包括:
// opacity: 0.6; // 降低透明度
// cursor: not-allowed; // 显示禁用光标
// pointer-events: none; // 禁用鼠标事件
}
}
上下文选择器
.nav {
& &-item {
// .nav .nav-item
}
}
媒体查询中的使用
.sidebar {
width: 300px;
@media (max-width: 768px) {
& {
width: 100%;
}
}
}
4. 特殊用法技巧
位置控制
.parent {
.child & {
// 编译为 .child .parent
//反转嵌套关系
}
}
多重引用
.foo, .bar {
& + & {
// 编译为 .foo + .foo, .foo + .bar, .bar + .foo, .bar + .bar
}
}
与属性选择器结合
[lang="en"] {
& .header {
// [lang="en"] .header
}
}
生成 BEM
命名
.block {
&__element {
// .block__element
&--modifier {
// .block__element--modifier
}
}
}
5. 在示例代码中的其他潜在应用
结构伪类
// 列表项基础样式
.list-item {
// 设置奇数行背景色(第1、3、5...项)
// :nth-child(odd) 是一个CSS伪类选择器,匹配父元素下奇数位置的子元素
// 常用于实现斑马纹/隔行变色的表格或列表效果
&:nth-child(odd) {
background: #f5f5f5; // 浅灰色背景
}
// 移除最后一个列表项的底部边框
// :last-child 是一个CSS伪类选择器,匹配父元素下最后一个子元素
// 常用于消除列表末尾元素的分隔线/边框
&:last-child {
border-bottom: none; // 取消底部边框
}
}
状态伪类
.link {
&:visited {
color: purple;
}
&:active {
color: red;
}
}
表单相关
.input {
&:focus {
outline: 2px solid blue;
}
&:disabled {
opacity: 0.5;
}
}
6. 注意事项
-
不能单独使用:
&
必须作为选择器的一部分,不能单独存在 -
位置敏感:
&-suffix
和suffix-&
会产生不同结果 -
多重嵌套:深层嵌套时
&
会包含所有父级选择器 -
与@at-root结合:可以跳出嵌套结构(
@at-root
是 SCSS 中的一个特殊指令,它的作用是让规则跳出当前的嵌套层级,直接在根层级输出样式规则)
7. 实际应用示例
// 生成按钮的各种状态
.btn {
&-primary {
background: blue;
&:hover {
background: darken(blue, 10%);
}
&:disabled {
background: lighten(blue, 30%);
}
}
&-large {
padding: 1em 2em;
@media (max-width: 600px) {
& {
padding: 0.8em 1.5em;
}
}
}
}
十. @Mixins & @include
1. Mixin 基础概念
-
Mixin 是 Sass 中的一种可重用代码块
-
类似于函数,可以定义一次然后多次调用
-
用于减少重复代码,提高可维护性
2. 定义 Mixin
使用 @mixin
指令定义:
@mixin mixin-name($parameter: default-value) {
// CSS 属性或规则
}
/**
* 定义一个按钮样式的 Mixin
*
* 这个 Mixin 提供了基础的按钮样式,包括:
* - 文本修饰、光标样式、显示方式
* - 边框、内边距、圆角
* - 可自定义的背景颜色
*
* @param {Color} $bg-color - 按钮背景颜色,默认值为 #e2e2e2(浅灰色)
*/
@mixin btn($bg-color: #e2e2e2) {
// 移除文本下划线
text-decoration: none;
// 设置光标为指针形状(表示可点击)
cursor: pointer;
// 设置为行内块级元素(既保持行内特性,又可以设置宽高)
display: inline-block;
// 移除边框
border: 0;
// 设置内边距:垂直方向使用 $base-padding,水平方向是垂直方向的2倍
padding: $base-padding $base-padding * 2;
// 设置圆角,使用全局定义的圆角变量
border-radius: $base-border-radius;
// 设置背景颜色,使用传入的参数值
background-color: $bg-color;
}
/**
* 使用示例:
* .primary-button {
* @include btn(#3498db); // 使用蓝色背景
* }
*
* .default-button {
* @include btn; // 使用默认灰色背景
* }
*/
3. 使用 Mixin
使用 @include
指令调用 mixin:
.selector {
@include mixin-name(arguments);
}
.btn {
@include btn; // 使用默认参数
}
.btn-primary {
@include btn(#007bff); // 传递参数
}
4. Mixin 参数
-
可以定义多个参数:
@mixin name($param1, $param2)
-
支持默认值:
@mixin name($param: default)
-
可以传递变量或具体值
5. Mixin 的高级用法
嵌套使用
/**
* 定义一个悬停效果 Mixin
*
* 这个 Mixin 提供了处理元素悬停状态的便捷方式,
* 允许通过 @content 传递自定义的悬停样式
*
* 特点:
* - 自动处理 :hover 伪类
* - 通过 @content 支持自定义悬停样式
*/
@mixin hover-effect {
// 定义 :hover 伪类
&:hover {
// @content 允许在调用时传入额外的样式规则
@content;
}
}
/**
* 使用示例 - 按钮悬停效果
*
* 这里演示如何为按钮添加悬停时的背景色变暗效果
* 使用 Sass 的 darken() 函数使颜色加深 10%
*/
.button {
// 调用 hover-effect mixin 并传入自定义样式
@include hover-effect {
// 悬停时背景色变暗 10%
background-color: darken($color, 10%);
}
}
/**
* 其他使用场景示例:
*
* .card {
* @include hover-effect {
* transform: scale(1.05);
* box-shadow: 0 5px 15px rgba(0,0,0,0.1);
* }
* }
*
* .link {
* @include hover-effect {
* text-decoration: underline;
* color: $primary-color;
* }
* }
*/
与循环结合使用
示例中与 @each
循环结合:
@each $key, $val in $colors {
.btn-#{$key} {
@include btn($val);
&:hover {
/**
* 定义悬停状态样式
* 使用 lighten() 函数使背景色变亮5%
*/
background-color: lighten($val, 5);
}
}
}
条件逻辑
可以在 mixin 中使用 @if
, @else
等条件语句
6. 实际应用示例
基础按钮样式
.btn {
@include btn; // 使用默认背景色
}
颜色变体按钮
.btn-primary {
@include btn(#007bff);
}
轮廓按钮
.btn-outlined-primary {
@include btn(#fff); // 白色背景
border: $base-border-thickness solid #007bff; // 蓝色边框
&:hover {
background-color: #007bff; // 悬停时变为蓝色背景
}
}
7. 优点总结
-
代码复用:避免重复编写相同样式
-
参数化:通过参数创建灵活可配置的样式
-
维护简单:修改一处即可全局更新
-
组织性好:将相关样式组合在一起
十一. Functions(函数)
1. 函数基础概念
-
函数(Function) 是 Sass 中可重用的代码块,用于计算并返回值
-
与 mixin 不同:函数用于计算值,mixin 用于生成样式
-
使用
@function
定义,@return
返回值
2. 自定义函数语法
@function function-name($parameters) {
// 计算逻辑
@return $value;
}
示例:
@function light-comp($color) {
$complement: complement($color);
$light-complement: lighten($complement, 30%);
@return $light-complement;
}
3. 函数参数
-
可以接受多个参数
-
支持默认参数值
-
参数可以是任意 Sass 数据类型
4. 函数调用
selector {
property: function-name(arguments);
}
示例:
.btn-complement-primary {
color: light-comp($primary-color);
}
5. 内置函数分类
颜色函数
-
lighten($color, $amount)
- 使颜色变亮 -
darken($color, $amount)
- 使颜色变暗 -
complement($color)
- 返回补色 -
mix($color1, $color2)
- 混合颜色
数字函数
-
percentage($number)
- 转换为百分比 -
round($number)
- 四舍五入 -
min($numbers...)
- 取最小值
字符串函数
-
quote($string)
- 添加引号 -
str-length($string)
- 获取长度
列表函数
-
length($list)
- 获取列表长度 -
nth($list, $n)
- 获取第n项
6. 实际应用示例
颜色计算函数
@function light-comp($color) {
$complement: complement($color); // 获取补色
$light-complement: lighten($complement, 30%); // 补色变亮30%
@return $light-complement;
}
按钮组件应用
.btn-complement-#{$key} {
@include btn($val); // 基础按钮样式
color: light-comp($val); // 使用函数计算文字颜色
&:hover {
color: $val; // 悬停时原始颜色
background-color: light-comp($val); // 使用函数计算背景色
}
}
7. 函数与 mixin 的区别
特性 | 函数(Function) | Mixin |
---|---|---|
用途 | 计算并返回值 | 生成CSS样式规则 |
定义方式 | @function | @mixin |
返回值 | 必须使用 @return | 不返回值 |
调用方式 | 直接使用函数名 | 使用 @include |
输出结果 | 返回单个值 | 输出CSS规则 |
8. 高级技巧
递归函数
@function factorial($number) {
@if $number == 1 {
@return 1;
}
@return $number * factorial($number - 1);
}
参数列表
@function sum($numbers...) {
$sum: 0;
@each $number in $numbers {
$sum: $sum + $number;
}
@return $sum;
}
条件逻辑
@function contrast-color($color) {
@if lightness($color) > 50% {
@return #000; // 浅色背景用黑色文字
} @else {
@return #fff; // 深色背景用白色文字
}
}
十二. 创建实用工具类
1. 实用工具类核心概念
什么是实用工具类
-
原子化CSS:单一职责的小型类
-
可复用样式:解决重复样式问题
-
高效开发:通过类名快速应用样式
优势
-
减少自定义CSS代码量
-
提高样式一致性
-
加快开发速度
-
便于维护和修改
示例代码:
@use 'sass:math';
$utilities: (
"padding": (
"prefix": "p",
"values": (
"0": 0,
"1": $base-padding,
"2": $base-padding * 2,
"3": $base-padding * 4,
"4": $base-padding * 6,
"5": $base-padding * 8
),
),
"padding-left": (
"prefix": "pl",
"values": (
"0": 0,
"1": $base-padding,
"2": $base-padding * 2,
"3": $base-padding * 4,
"4": $base-padding * 6,
"5": $base-padding * 8
),
),
"padding-right": (
"prefix": "pr",
"values": (
"0": 0,
"1": $base-padding,
"2": $base-padding * 2,
"3": $base-padding * 4,
"4": $base-padding * 6,
"5": $base-padding * 8
),
),
"padding-top": (
"prefix": "pt",
"values": (
"0": 0,
"1": $base-padding,
"2": $base-padding * 2,
"3": $base-padding * 4,
"4": $base-padding * 6,
"5": $base-padding * 8
),
),
"padding-bottom": (
"prefix": "pb",
"values": (
"0": 0,
"1": $base-padding,
"2": $base-padding * 2,
"3": $base-padding * 4,
"4": $base-padding * 6,
"5": $base-padding * 8
),
),
"margin": (
"prefix": "m",
"values": (
"0": 0,
"1": $base-margin,
"2": $base-margin * 2,
"3": $base-margin * 4,
"4": $base-margin * 6,
"5": $base-margin * 8
),
),
"margin-left": (
"prefix": "ml",
"values": (
"0": 0,
"1": $base-margin,
"2": $base-margin * 2,
"3": $base-margin * 4,
"4": $base-margin * 6,
"5": $base-margin * 8
),
),
"margin-right": (
"prefix": "mr",
"values": (
"0": 0,
"1": $base-margin,
"2": $base-margin * 2,
"3": $base-margin * 4,
"4": $base-margin * 6,
"5": $base-margin * 8
),
),
"margin-top": (
"prefix": "mt",
"values": (
"0": 0,
"1": $base-margin,
"2": $base-margin * 2,
"3": $base-margin * 4,
"4": $base-margin * 6,
"5": $base-margin * 8
),
),
"margin-bottom": (
"prefix": "mb",
"values": (
"0": 0,
"1": $base-margin,
"2": $base-margin * 2,
"3": $base-margin * 4,
"4": $base-margin * 6,
"5": $base-margin * 8
),
),
"opacity": (
"prefix": "o",
"values": (
"10": 0.1,
"20": 0.2,
"30": 0.3,
"40": 0.4,
"50": 0.5,
"60": 0.6,
"70": 0.7,
"80": 0.8,
"90": 0.9,
"100": 1,
),
),
"border-radius": (
"prefix": "br",
"values": (
"default": $base-border-radius,
"none": 0,
"xs": math.div($base-border-radius, 4),
"sm": math.div($base-border-radius, 2),
"lg": $base-border-radius * 2,
"full": 50%,
)
),
"display": (
"prefix": "display",
"values": (
"n": none,
"b": block,
"f": flex,
"i": inline,
"i-b": inline-block
)
),
"font-size": (
"prefix": "font",
"values": (
"sm": $font-size-sm,
"md": $base-font-size,
"lg": $font-size-lg,
"xl": $font-size-xl,
"xxl": $font-size-xxl
)
)
);
// generate utility classes
@each $property, $map in $utilities {
$prefix: map-get($map, "prefix");
$values: map-get($map, "values");
@each $k, $v in $values {
@if($k == "default") {
.#{$prefix} {
#{$property}: $v;
}
} @else {
.#{$prefix}-#{$k}{
#{$property}: $v;
}
}
}
}
2. 基础实现方法
数据结构设计
使用Sass Map嵌套结构:
$utilities: (
"属性名": (
"prefix": "类名前缀",
"values": (
"修饰符": 值,
// ...
)
)
// 更多属性...
);
核心循环结构
/**
* 实用工具类生成器
*
* 这段代码通过嵌套循环遍历 $utilities 映射,
* 自动生成一系列实用的原子化CSS类
*/
// 外层循环:遍历 $utilities 映射中的每个属性配置
@each $property, $map in $utilities {
// 从当前属性的配置映射中获取:
$prefix: map-get($map, "prefix"); // 类名前缀(如:"p"代表padding)
$values: map-get($map, "values"); // 值映射表(如:("0": 0, "1": 0.25rem))
// 内层循环:遍历当前属性的所有值配置
@each $key, $value in $values {
/**
* 生成工具类规则
* 格式:.前缀-修饰符 { 属性: 值; }
* 示例:
* - .p-1 { padding: 0.25rem; }
* - .mt-2 { margin-top: 0.5rem; }
*/
.#{$prefix}-#{$key} {
#{$property}: $value; // 动态设置CSS属性和值
}
}
}
/**
* 工作流程说明:
* 1. 第一层循环获取每个CSS属性(如padding/margin等)及其配置
* 2. 提取该属性的前缀(prefix)和值列表(values)
* 3. 第二层循环遍历值列表,为每个值生成对应的工具类
* 4. 最终生成大量格式统一的工具类,如:
* .p-0 { padding: 0; }
* .p-1 { padding: 0.25rem; }
* .m-2 { margin: 0.5rem; }
* ...等等
*/
/**
* 高级特性说明:
* 1. 动态属性名:通过 #{$property} 插入变量作为CSS属性
* 2. 动态类名:通过.#{$prefix}-#{$key} 生成可配置的类名
* 3. 完全数据驱动:只需修改 $utilities 映射即可调整生成的工具类
* 4. 与Sass运算结合:支持在values中使用Sass运算(如 $base-padding * 2)
*/
/**
* 典型应用场景:
* <div class="p-2 m-1 br-sm"> // 同时应用padding、margin和border-radius
* <button class="p-3 hover:m-2"> // 结合状态变体使用
*/
3. 代码解析(基于示例代码)
数学计算模块
@use 'sass:math'; // 导入Sass数学模块
// 用于数学运算如除法:math.div($a, $b)
间距系统设计
"padding": (
"prefix": "p", // 类名前缀
"values": (
"0": 0, // p-0 → padding: 0
"1": $base-padding, // p-1 → padding: 基础间距
"2": $base-padding * 2, // p-2 → padding: 2倍基础间距
// ...
)
)
特殊值处理
@if($k == "default") {
// 生成无修饰符类名 (如: .br)
.#{$prefix} { #{$property}: $v; }
} @else {
// 常规带修饰符类名 (如: .br-sm)
.#{$prefix}-#{$k} { #{$property}: $v; }
}
4. 实用工具类分类示例
间距工具
类别 | 前缀 | 示例类名 | 效果 |
---|---|---|---|
全向间距 | p | p-1, p-2 | 控制所有方向内边距 |
左间距 | pl | pl-1, pl-2 | 控制左侧内边距 |
右间距 | pr | pr-1, pr-2 | 控制右侧内边距 |
上间距 | pt | pt-1, pt-2 | 控制顶部内边距 |
下间距 | pb | pb-1, pb-2 | 控制底部内边距 |
外边距 | m | m-1, m-2 | 控制所有方向外边距 |
其他实用工具
类别 | 前缀 | 示例类名 | 效果 |
---|---|---|---|
透明度 | o | o-50, o-100 | 设置元素透明度 |
圆角 | br | br-sm, br-lg | 控制元素圆角大小 |
显示模式 | display | display-f, display-b | 控制元素显示类型 |
字体大小 | font | font-sm, font-lg | 控制文字大小 |
5. 高级技巧
响应式工具类
@each $breakpoint, $value in $breakpoints {
@media (min-width: $value) {
@each $property, $map in $utilities {
// 生成带断点前缀的类 (如: md:p-2)
}
}
}
状态变体
@each $state in (hover, focus, active) {
@each $property, $map in $utilities {
// 生成状态类 (如: hover:p-2)
}
}
自定义值扩展
"padding": (
"values": map-merge(
(
"6": $base-padding * 10,
"7": $base-padding * 12
),
map-get($utilities, "padding", "values")
)
)
6. 生成结果示例
输入Sass:
"border-radius": (
"prefix": "br",
"values": (
"default": 4px,
"none": 0,
"full": 50%
)
)
输出CSS:
.br { border-radius: 4px; }
.br-none { border-radius: 0; }
.br-full { border-radius: 50%; }
十三. 媒体查询
1. @media 指令
@media
是 CSS 的媒体查询指令,在 Sass 中可以直接使用,用于创建响应式设计。
基本语法
@media (media-feature) {
/* CSS 规则 */
}
2. @content 指令
@content
是 Sass 的 mixin 特性,用于在 mixin 中插入额外的内容(来自调用者传递的样式块)。
基本用法
@mixin example {
.container {
@content; // 这里会插入调用时传递的内容
}
}
@include example {
color: red; //传递到@content
}
3. 结合使用 @media 和 @content
在响应式设计中,我们经常结合两者创建响应式 mixin。
断点(Breakpoint)是响应式网页设计中的核心概念,指的是预先设定的屏幕宽度临界值,当浏览器窗口宽度达到这些特定值时,网页布局或样式会相应调整。
代码分析
// 定义断点 map
$breakpoints: (
"xs": 0,
"sm": 480px,
"md": 720px,
"lg": 960px,
"xl": 1200px,
);
// 为断点创建 mixin
@mixin xs {
@media (min-width: map-get($breakpoints, "xs")) {
@content;
}
}
// 通用断点 mixin
@mixin breakpoint($bp: 0) {
@media (min-width: $bp) {
@content;
}
}
4. 实际应用示例
.responsive-test {
@include xs {
color: red; // 0px 及以上生效
}
@include sm {
color: blue; // 480px 及以上生效
}
@include md {
color: green; // 720px 及以上生效
}
@include lg {
color: purple; // 960px 及以上生效
}
@include xl {
color: orange; // 1200px 及以上生效
}
@include breakpoint(1400px) {
color: pink; // 1400px 及以上生效
}
}
编译后的 CSS
@media (min-width: 0) {
.responsive-test {
color: red;
}
}
@media (min-width: 480px) {
.responsive-test {
color: blue;
}
}
@media (min-width: 720px) {
.responsive-test {
color: green;
}
}
@media (min-width: 960px) {
.responsive-test {
color: purple;
}
}
@media (min-width: 1200px) {
.responsive-test {
color: orange;
}
}
@media (min-width: 1400px) {
.responsive-test {
color: pink;
}
}
十四. 网格系统
1. 网格系统基础概念
网格系统是一种用于页面布局的结构化方法,将页面划分为若干列,使内容能够有序排列。主要包含以下要素:
-
容器 (Container):包裹整个网格系统的外层元素
-
行 (Row):包含列的横向布局容器
-
列 (Column):实际承载内容的垂直区块
-
间距 (Gutter):列与列之间的间隔
2. 核心变量定义
$grid-columns: 12; // 定义网格系统为12列
$grid-gaps: (
"0": 0,
"1": 10px,
"2": 20px,
"3": 30px,
); // 定义间隙大小等级
$layout-values: flex-start, flex-end, center, space-between, space-around; // 定义flex布局对齐方式
3. 基础布局类
容器 (Container)
.container {
width: 100%;
max-width: 1200px; // 最大宽度限制
margin: 0 auto; // 水平居中
padding: 0 20px; // 左右内边距
box-sizing: border-box; // 盒模型计算方式
}
行 (Row)
.row {
display: flex; // 使用flex布局
flex-flow: row wrap; // 横向排列且允许换行
}
4. 网格间隙系统
使用Sass循环生成不同间隙等级的类:
@each $key, $val in $grid-gaps {
.gap-#{$key} > * //选择当前元素的所有直接子元素
{
padding: $val; // 子元素内边距
}
.gap-#{$key} {
margin-left: -$val; // 负外边距抵消子元素内边距
margin-right: -$val;
}
}
5. 对齐方式类
使用Sass循环生成不同对齐方式的类:
@each $val in $layout-values {
.justify-#{$val} {
justify-content: $val; // flex布局主轴对齐
}
}
6. 响应式列系统
基本列结构
.col-{数字}-{断点} {
box-sizing: border-box;
flex-grow: 0; // 不允许自动扩展
width: 百分比宽度; // 根据列数计算
}
使用数学计算列宽
width: math.div($i * 100%, $grid-columns);
// 等同于 ($i / $grid-columns) * 100%
响应式实现
为每个断点生成对应的列类:
@include xs {
@for $i from 1 through $grid-columns {
.col-#{$i}-xs {
/* ... */
}
}
}
7.示例代码
@use "sass:math";
$grid-columns: 12;
$grid-gaps: (
"0": 0,
"1": 10px,
"2": 20px,
"3": 30px,
);
$layout-values: flex-start, flex-end, center, space-between, space-around;
// base layout classes
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
box-sizing: border-box;
}
.row {
display: flex;
flex-flow: row wrap;
}
// grid gaps
@each $key, $val in $grid-gaps {
.gap-#{$key} > * {
padding: $val;
}
.gap-#{$key} {
margin-left: -$val;
margin-right: -$val;
}
}
// justify content classes
@each $val in $layout-values {
.justify-#{$val} {
justify-content: $val;
}
}
// col classes
@include xs {
@for $i from 1 through $grid-columns {
.col-#{$i}-xs {
box-sizing: border-box;
flex-grow: 0;
width: math.div($i * 100%, $grid-columns);
}
}
}
@include sm {
@for $i from 1 through $grid-columns {
.col-#{$i}-sm {
box-sizing: border-box;
flex-grow: 0;
width: math.div($i * 100%, $grid-columns);
}
}
}
@include md {
@for $i from 1 through $grid-columns {
.col-#{$i}-md {
box-sizing: border-box;
flex-grow: 0;
width: math.div($i * 100%, $grid-columns);
}
}
}
@include lg {
@for $i from 1 through $grid-columns {
.col-#{$i}-lg {
box-sizing: border-box;
flex-grow: 0;
width: math.div($i * 100%, $grid-columns);
}
}
}
@include xl {
@for $i from 1 through $grid-columns {
.col-#{$i}-xl {
box-sizing: border-box;
flex-grow: 0;
width: math.div($i * 100%, $grid-columns);
}
}
}
十五. @extend
1. @extend 基本概念
@extend
是 Sass 中的一个功能,允许一个选择器继承另一个选择器的样式规则。它可以减少重复代码,使 CSS 输出更高效。
基本语法
.selector1 {
@extend .selector2;
}
2. 示例代码
//占位符选择器
%flex-layout {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
/*
普通类选择器
.flex-layout {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
**/
.navbar {
// @extend .flex-layout; // 继承普通类选择器
@extend %flex-layout; // 继承占位符选择器
padding: $base-padding $base-padding * 2;
box-shadow: $base-box-shadow;
.site-title {
font-size: $font-size-lg;
}
.container {
@extend %flex-layout; // 再次继承相同的占位符选择器
}
}
3. 占位符选择器 (%) 与普通类选择器的区别
@extend %flex-layout
-
继承的是占位符选择器(以
%
开头) -
占位符选择器本身不会被编译到最终的 CSS 中
-
只有实际被继承的样式会被输出
-
适用于只作为基础样式被继承,不需要单独使用的场景
SASS代码
%flex-layout {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.navbar {
@extend %flex-layout;
padding: 1rem;
}
编译后的CSS代码
.navbar {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.navbar {
padding: 1rem;
}
@extend .flex-layout
-
继承的是普通的类选择器
-
原始的类选择器会被保留在最终的 CSS 中
-
即使没有被继承,原始类也会出现在 CSS 中
-
适用于既需要作为基础样式,也需要单独使用的场景
SASS代码
.flex-layout {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.navbar {
@extend .flex-layout;
padding: 1rem;
}
编译后的CSS代码
.flex-layout, .navbar {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.navbar {
padding: 1rem;
}
4. @extend 与 @mixin 的区别
特性 | @extend | @mixin |
---|---|---|
语法 | 继承已有选择器的样式 | 定义可重用的样式块 |
代码生成 | 合并选择器,减少重复 | 复制样式到每个调用处 |
参数 | 不支持参数 | 支持参数,更灵活 |
输出结果 | 生成的 CSS 更简洁 | 生成的 CSS 可能有重复 |
适用场景 | 样式完全相同或高度相似时 | 需要根据不同参数生成样式时 |
性能 | 编译后的 CSS 通常更小 | 可能产生更多重复代码 |
占位符 | 可与占位符选择器配合使用 | 总是会生成代码 |
何时使用 @extend:
-
当多个元素共享完全相同的一组样式时
-
当你希望保持生成的 CSS 尽可能简洁时
-
当不需要动态变化样式时
何时使用 @mixin:
-
当需要根据参数生成不同样式时
-
当样式块需要在多个地方使用但有小部分差异时
-
当需要更灵活地控制输出时
5. @extend 的注意事项
-
优先使用占位符选择器:当样式只是作为基础被继承时,使用
%
占位符可以避免生成不必要的 CSS。 -
避免过度嵌套:过度使用@extend可能导致选择器链过长,影响性能。
-
注意继承范围:@extend会继承所有相关的样式,包括嵌套规则。
-
与媒体查询配合时要小心:@extend不能跨媒体查询边界继承样式。
-
用于基础布局和工具类:如示例中的flex布局,非常适合用@extend共享。
6. @each 与 @extend 的结合使用
@each $key, $val in $colors {
.navbar-#{$key} {
@extend .navbar; // 继承.navbar的所有样式
background-color: $val; // 然后添加自己的背景色
}
}
十六. @use 和 @forward
1.@use 基础用法
基本语法
@use '路径/模块文件'; // 默认命名空间
@use 'buttons' as btn; // 自定义命名空间
@use 'colors' as *; // 取消命名空间(直接使用成员)
实际案例
// _variables.scss
$primary: #3498db;
$padding: 1rem;
// style.scss
@use 'variables' as vars;
.button {
background: vars.$primary;
padding: vars.$padding;
}
关键特性
-
作用域隔离:模块变量不会污染全局
-
自动去重:同一文件多次引用只编译一次
-
必须带引号:
@use 'module'
(不能省略引号)
2.@use 高级功能
配置模块 (!default + with)
// _config.scss
$theme-color: blue !default;
$font-size: 16px !default;
// main.scss
@use 'config' with (
$theme-color: red,
$font-size: 18px
);
私有成员(模块内部使用)
// _utils.scss
$-private-var: 10px; // 只能在当前文件使用
@function add-padding($val) {
@return $val + $-private-var;
}
3.@forward
基础转发
// _library.scss
@forward 'buttons';
@forward 'forms';
控制转发的成员
场景 | 语法示例 | 说明 |
---|---|---|
添加前缀 | @forward "buttons" as btn-* | 所有成员变成 btn- 前缀 |
隐藏特定成员 | @forward "forms" hide $secret | 不转发指定变量/混合器 |
只转发部分成员 | @forward "grid" show row, col | 仅转发明确指定的成员 |
转发时配置默认值
// bootstrap.scss
@forward 'config' with (
$theme-color: purple !default
);
4.@use vs @forward 对比
特性 | @use | @forward |
---|---|---|
主要用途 | 使用其他模块的功能 | 转发模块给其他文件使用 |
是否加载CSS | 是 | 否 |
能否访问成员 | 能 | 不能(除非同时用@use) |
典型使用场景 | 组件样式文件中 | 库的入口文件 |
5.SASS 的 @forward 和 JavaScript 的 export 的区别
对比表
特性 | SASS 的 @forward | JavaScript 的 export | 异同点说明 |
---|---|---|---|
基本功能 | 转发其他模块的成员 | 导出变量/函数/类 | 功能相似,都是暴露内容 |
是否保留原模块 | ✅ 是(可同时使用@use加载) | ❌ 否(导出后原模块不保留) | SASS更灵活 |
重命名能力 | ✅ 支持(as prefix-* 语法) | ✅ 支持(export { x as y } ) | 两者都支持 |
选择性暴露 | ✅ 支持(show/hide) | ✅ 支持(按需export) | 两者都支持 |
默认导出 | ❌ 不支持 | ✅ 支持(export default) | JS更灵活 |
多层转发 | ✅ 支持(A → B → C) | ✅ 支持(多层re-export) | 两者都支持 |
实际效果 | 创建"通道"不直接使用 | 真正导出值 | JS是值传递,SASS是引用传递 |
相似点:都是"暴露内容"
// SASS(转发mixin)
@forward 'mixins' show flex-center;
// JS(导出函数)
export { flexCenter } from './utils.js';
关键区别点
1.是否保留原模块
// SASS中可以同时使用(转发且自己用)
@forward 'mixins';
@use 'mixins'; // 合法!
// JS中不能这样用
export { foo } from './utils.js';
import { foo } from './utils.js'; // 冗余!
2.重命名方式
// SASS(批量加前缀)
@forward 'buttons' as btn-*;
// JS(单个重命名)
export { button as btn } from './components.js';
3.默认导出
// JS支持默认导出
export default function() {...}
// SASS没有等价功能
// 最近似的是:
@forward 'config' with ($color: red !default);
6.注意事项
** 为什么要用@use替代@import?**
-
@import
会导致:-
全局命名冲突
-
重复编译
-
无法控制作用域
-
-
@use
解决所有这些问题
什么时候该用 @forward?
- 创建样式库入口文件时
// bootstrap.scss
@forward 'grid';
@forward 'buttons';
@forward 'forms';
- 需要隐藏内部实现细节时
@forward 'internal/utils' hide $_privateVar;
- 统一前缀时
// company-ui.scss
@forward 'buttons' as btn-*;
@forward 'grid' as grid-*;
** 如何查看模块有哪些成员?**
@debug meta.module-variables('模块名');
@debug meta.module-functions('模块名');
@debug meta.module-mixins('模块名');
7.总结:“转发就像快递站,不生产包裹(@use),只中转包裹,还能给包裹贴新标签(as)或拆包重组(show/hide)”
十七. @extend @error @warn
1.@debug - 开发调试工具
基本用法
@debug <表达式>;
// 示例:检查变量值
$base-font-size: 16px;
@debug "当前字体大小:", $base-font-size;
// 输出:DEBUG: 当前字体大小:16px
特点
-
仅开发阶段可见(编译后不出现在CSS中)
-
打印任意SASS数据类型(颜色、列表、map等)
-
支持多参数逗号分隔(自动加空格连接)
实用技巧
// 调试map结构
$colors: (primary: #3498db, secondary: #2ecc71);
@debug "颜色映射表:", $colors;
// 输出:DEBUG: 颜色映射表: (primary: #3498db, secondary: #2ecc71)
2.@warn - 警告
基本用法
@warn "<警告信息>";
// 示例:弃用提示
@mixin old-mixin {
@warn "此mixin已弃用,请使用new-mixin代替";
// ...旧代码
}
特点
-
会显示警告但继续编译
-
黄色警告信息(在终端/编译工具中突出显示)
-
适合标记即将废弃的功能
实际应用
// 检查颜色对比度
@function contrast-check($bg, $text) {
@if (lightness($bg) > 50% and lightness($text) > 50%) {
@warn "低对比度:浅色背景(#{$bg})配浅色文字(#{$text})";
}
@return mix($bg, $text, 10%);
}
3.@error - 致命错误
基本用法
@error "<错误信息>";
// 示例:参数验证
@mixin square($size) {
@if type-of($size) != number {
@error "参数$size必须是数字,当前是 #{type-of($size)}";
}
width: $size;
height: $size;
}
特点
-
立即停止编译
-
红色错误信息(强制开发者修复)
-
适合参数验证等关键错误
示例
// 验证颜色格式
@function check-hex($color) {
@if str-slice(#{$color}, 1, 1) != "#" {
@error "颜色值#{$color}必须为16进制格式(如#FFF)";
}
@return $color;
}
4.三者的对比总结
指令 | 输出颜色 | 是否中断编译 | 典型使用场景 |
---|---|---|---|
@debug | 灰色 | 否 | 开发时检查变量/表达式值 |
@warn | 黄色 | 否 | 废弃功能提示/非关键问题警告 |
@error | 红色 | 是 | 参数验证/必须修复的致命错误 |