SASS入门指南

一. 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     // 启动监听
)

工作流程解析:
  1. 文件输入src() 读取项目根目录的 index.scss

  2. 编译转换sass() 调用 Dart Sass 编译器进行转换

  3. 文件输出dest() 将生成的 CSS 写入 css 目录

  4. 持续监听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;
    
  • 支持多种数据类型:

    • 颜色:#326deergb(255, 0, 0)
    • 数字:161.5
    • 字符串:"hello"sans-serif
    • 布尔值:truefalse
    • 列表: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%;
}
单位运算规则
  1. ** 兼容单位运算**:
   @debug 10px + 20px;  // 30px
   @debug 1in + 6px;    // 102px(1in = 96px)
  1. 相对单位计算
    @debug 10px * 3rem;  // 30px*rem(无效单位会报错)
  1. 单位转换
    $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.注意事项
  1. Map 不可变性:所有 map 函数都返回新 map,不修改原始 map
    $new-map: map-remove($colors, "primary"); // 原 $colors 不变
  1. 键的类型:键可以是任何 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() 函数的补充说明:
  1. 函数语法mix($color1, $color2, $weight: 50%)

  2. 参数解释

    • $color1:第一种要混合的颜色

    • $color2:第二种要混合的颜色

    • $weight:可选参数,表示第一种颜色的权重比例(默认50%)

  3. 在代码中的应用

    • 浅色变体:将原色与白色混合,$i * 10 从10%到90%递增

    • 深色变体:将原色与黑色混合,$i * 10 从10%到90%递增

  4. 数学关系

    • 当 $weight 为 0% 时,结果完全是 $color2

    • 当 $weight 为 100% 时,结果完全是 $color1

    • 当 $weight 为 50% 时,两种颜色各占一半


3. @each 和 @for 的区别
特性@each@for
用途遍历列表或映射中的元素按数字范围循环
循环条件集合中的每个元素数字范围(start到end)
获取内容可以获取键和值只能获取当前数字
典型场景生成基于一组颜色/尺寸的类生成有规律的序号类(如1-9)
灵活性更适合处理已知的有限集合更适合处理需要计算的数字序列

4. 组合使用技巧

在实际项目中,@each 和 @for 经常组合使用,如示例中:

  1. 先用 @each 遍历颜色映射

  2. 然后在每个颜色循环内部,用 @for 生成该颜色的深浅变体

这种组合可以高效地生成大量有规律的CSS类,减少重复代码。


5. 实用提示
  1. 循环变量可以使用任意名称,但应保持语义化(如$key$val$i)

  2. 在循环体内可以使用插值语法 #{$var} 动态生成类名

  3. 嵌套循环时要小心选择变量名,避免冲突

  4. 过度使用循环可能会生成大量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. 注意事项
  1. 单位敏感10px == 10 返回 false,因为单位不同

  2. 颜色比较red == #ff0000 返回 true,因为它们是相同颜色

  3. 空值判断@if $var { ... } 在 $var 为 null 或 false 时为假

  4. 列表判断@if index($list, $item) 检查元素是否在列表中

  5. 嵌套条件:可以嵌套使用 @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. 注意事项
  1. 不能单独使用& 必须作为选择器的一部分,不能单独存在

  2. 位置敏感&-suffix 和 suffix-& 会产生不同结果

  3. 多重嵌套:深层嵌套时 & 会包含所有父级选择器

  4. 与@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. 优点总结
  1. 代码复用:避免重复编写相同样式

  2. 参数化:通过参数创建灵活可配置的样式

  3. 维护简单:修改一处即可全局更新

  4. 组织性好:将相关样式组合在一起

十一. 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. 实用工具类分类示例
间距工具
类别前缀示例类名效果
全向间距pp-1, p-2控制所有方向内边距
左间距plpl-1, pl-2控制左侧内边距
右间距prpr-1, pr-2控制右侧内边距
上间距ptpt-1, pt-2控制顶部内边距
下间距pbpb-1, pb-2控制底部内边距
外边距mm-1, m-2控制所有方向外边距
其他实用工具
类别前缀示例类名效果
透明度oo-50, o-100设置元素透明度
圆角brbr-sm, br-lg控制元素圆角大小
显示模式displaydisplay-f, display-b控制元素显示类型
字体大小fontfont-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 的注意事项
  1. 优先使用占位符选择器:当样式只是作为基础被继承时,使用%占位符可以避免生成不必要的 CSS。

  2. 避免过度嵌套:过度使用@extend可能导致选择器链过长,影响性能。

  3. 注意继承范围:@extend会继承所有相关的样式,包括嵌套规则。

  4. 与媒体查询配合时要小心:@extend不能跨媒体查询边界继承样式。

  5. 用于基础布局和工具类:如示例中的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 的 @forwardJavaScript 的 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?
  1. 创建样式库入口文件时
// bootstrap.scss
@forward 'grid';
@forward 'buttons';
@forward 'forms';
  1. 需要隐藏内部实现细节时
@forward 'internal/utils' hide $_privateVar;
  1. 统一前缀时
 // 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红色参数验证/必须修复的致命错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值