第一章:SCSS 基础核心语法
第一章:SCSS 基础核心语法
Prorise第一章:SCSS 基础核心语法
摘要: 欢迎来到 SCSS 的世界!在本章中,我们将正式从原生 CSS 迈向更强大、更具工程化能力的 CSS 预处理器。您将学习 SCSS 的核心语法,包括 变量 的声明与使用、嵌套 规则如何简化代码结构,以及最重要的——如何通过现代 模块化 方案(@use 与 @forward)来组织一个清晰、可扩展、无污染的 SCSS 项目。本章还将涵盖编译环境的搭建与核心 调试技巧,为您后续的学习扫清一切障碍。
在本章的学习地图中,我们将:
- 首先,明确 SCSS 语法 并 搭建编译环境,掌握将
.scss文件“翻译”成浏览器认识的.css文件的方法,并学会 Source Maps 调试技巧。 - 接着,学习 变量 (
$),告别在代码中重复书写“魔术数字”的时代。 - 然后,我们将深入 嵌套 (Nesting),用更直观的方式编写具有清晰层级关系的样式。
- 最后,我们将学习 SCSS 最重要的工程化特性——模块化,并搭建一个科学的、可扩展的 SCSS 项目结构。
1.1. 语法与编译环境
1.1.1. SCSS vs. Sass:理解两种语法
正如序章所述,我们选择学习的 SCSS (.scss 文件) 语法是 CSS 的超集。这意味着任何有效的 CSS 代码本身就是有效的 SCSS 代码,您可以在 .scss 文件中无缝地编写和粘贴任何原生 CSS。这是它学习曲线平缓的关键。
1.1.2. 搭建编译环境
浏览器不直接认识 SCSS,它只认识 CSS。因此,我们需要一个“翻译官”——编译器,将我们的 .scss 文件转换为 .css 文件。在 2025 年,我们几乎总是在一个现代前端项目(如使用 Vite 或 Webpack)中开发,这些工具已经内置了 SCSS 的编译能力,通常我们只需安装一个依赖即可。
独立使用: 如果您想独立编译,官方 唯一推荐 的实现是 Dart Sass。
- 安装 (需要 Node.js 环境):
1
npm install -g sass
- 编译:
1
2
3
4
5# 将 input.scss 编译成 output.css
sass input.scss output.css
# 开启“监视”模式,每当 input.scss 文件保存时,自动重新编译
sass --watch input.scss output.css
1.1.3. 调试技巧:精通 Source Maps
痛点背景: 当你在浏览器开发者工具中审查一个元素时,你看到的样式规则指向的是编译后的 .css 文件(例如 output.css 的第 158 行),但你真正需要修改的是 .scss 源文件(例如 _card.scss 的第 12 行)。在复杂的项目中,这种“源码映射”的缺失会极大地拖慢调试效率。
解决方案: Source Maps (.css.map 文件) 就是为了解决这个问题而生的。它像一张地图,记录了编译后的 CSS 代码与 SCSS 源码之间的精确位置对应关系。
如何开启:
- 构建工具: Vite、Webpack 等工具在开发模式下 (
development mode) 默认开启 Source Maps。 - 命令行:
1
2# Dart Sass 默认就会生成 Source Map
sass --watch input.scss output.css
掌握 Source Maps 是 SCSS 开发的必备技巧。它能让你的开发体验如丝般顺滑,仿佛浏览器能直接运行 SCSS 一样。
1.2. 变量 ($) 与数据类型
1.2.1. 变量的声明、作用域与 !default
与原生 CSS 变量 (--var) 不同,SCSS 变量以 $ 符号开头,它在 编译时 就会被替换为静态的值。
- 声明与使用:
1
2
3
4
5
6
7$primary-color: #3498db;
$base-spacing: 16px;
.button {
background-color: $primary-color;
padding: $base-spacing / 2 $base-spacing;
} - 作用域: SCSS 变量存在块级作用域。
1
2
3
4
5
6
7
8
9
10
11
12$global-color: black;
.container {
$local-color: white; /* 仅在 .container 内部有效 */
background-color: $global-color;
color: $local-color;
}
.footer {
// 错误!无法访问 .container 内部的 $local-color
// color: $local-color;
} !default: 这个标志用于设置变量的 默认值。如果该变量已经被赋值,那么!default这一行将被忽略;如果变量尚未赋值,则使用该默认值。这在编写可配置的组件库或框架时非常有用。1
2
3
4
5
6
7// _library.scss
$button-bg: #3498db !default; // 库提供一个默认颜色
.button { background-color: $button-bg; }
// my-project.scss
$button-bg: #e74c3c; // 在导入库之前,覆盖掉默认值
@use 'library'; // 此时按钮的背景色将是红色
1.2.2. SCSS 数据类型简介
SCSS 支持多种数据类型,为编写逻辑和函数提供了基础。
| 数据类型 | 示例 | 描述 |
|---|---|---|
| Number | 16px, 1.5, 10% | 带或不带单位的数字。 |
| String | "Hello", 'SCSS', bold | 带引号或不带引号的文本。 |
| Color | #fff, rgba(0,0,0,0.5) | 颜色值。 |
| Boolean | true, false | 布尔值。 |
| List | 1px 2px, (Helvetica, Arial) | 用空格或逗号分隔的一组值。 |
| Map | (key1: val1, key2: val2) | 键值对集合,类似 JSON 对象。 |
null | null | 表示空值。 |
1.3. 嵌套 (Nesting)
嵌套是 SCSS 最为人熟知的功能之一,它允许我们将层级选择器写得更像 HTML 结构,极大地提高了代码的可读性和组织性。
1.3.1. 选择器嵌套
1 | /* 传统 CSS 写法 */ |
1.3.2. 父选择器引用 (&) 的妙用
& 符号是一个特殊的选择器,它代表了 当前的父选择器。
- 用于伪类: 这是最常见的用法。
1
2
3
4
5
6
7a {
color: blue;
&:hover {
color: red;
}
}
// 编译为: a { color: blue; } a:hover { color: red; } - 用于拼接 BEM 类名:
&可以像字符串一样,与其他文本拼接,是实践 BEM 命名规范的神器。
1.3.3. 实战:使用嵌套和 & 快速构建 BEM 风格的卡片样式
任务: 使用 BEM 规范 (.card, .card__title, .card--primary) 来定义一个卡片组件,但用 SCSS 的嵌套和 & 功能来编写样式,保持代码的结构化。
1 | . 📂 scss |
文件路径: scss\index.scss
1 | .card { |
文件路径: index.html
1 |
|
1.4. 模块化 (@use 与 @forward):告别 @import
1.4.1. 痛点解析:@import 的全局污染问题
在旧的 Sass 语法中,@import 规则是组织样式的主要方式。但它的工作原理非常简单粗暴:将所有被导入文件的内容“复制粘贴”到同一个地方,最终编译成一个巨大的 CSS 文件。
这种机制导致了一个核心问题:全局作用域。所有文件中定义的变量、混合宏(mixin)和函数都存在于同一个全局命名空间下。这极易导致命名冲突,尤其是在大型项目中,你很可能在不知不觉中覆盖了另一个文件中的同名变量,从而引发难以追踪和调试的 bug。
1.4.2. @use:现代模块化核心
为了彻底解决 @import 的弊端,Dart Sass 引入了全新的 @use 规则。它借鉴了现代编程语言(如 JavaScript 的 import)的模块化思想,为 Sass 带来了真正的模块系统。
默认命名空间: 当你
@use 'variables';时,_variables.scss文件中的所有公开成员(变量、mixin 等)都会被加载到一个以文件名命名的命名空间中。你必须通过variables.前缀来访问它们,例如variables.$primary-color。这从根本上杜绝了命名冲突。私有成员: 在模块文件中,任何以
-或_开头的变量、mixin 或函数,都将被视为私有成员。这意味着它们只能在当前文件内部使用,无法被外部通过@use访问,从而实现了更好的封装。自定义别名: 如果模块名太长,你可以为它设置一个更短的别名,提高代码可读性。例如:
@use 'variables' as vars;,之后便可以通过vars.$primary-color来访问。
1.4.3. @forward:构建样式库的瑞士军刀
当项目结构变得复杂时,你可能不希望使用者 @use 多个底层模块文件。@forward 规则就是为此而生。它允许一个文件(通常是文件夹的入口文件,如 _index.scss)加载其他模块的成员,并将它们“转发”出去,使其对外部可见。
想象一下,abstracts 文件夹下有 _variables.scss 和 _mixins.scss。我们可以创建一个 abstracts/_index.scss 文件:
1 | // scss/abstracts/_index.scss |
这样,其他文件只需要 @use 'abstracts'; (Sass 会自动寻找 _index.scss),就可以通过 abstracts.$primary-color 和 @include abstracts.flex-center 同时访问到这两个模块的成员了,大大简化了模块的引用。
1.4.4. 实战:搭建一个科学的 SCSS 项目文件结构
现在,让我们结合所学,搭建一个业界流行的 7-1 Pattern 简化版结构,并学习如何正确组织和导入我们的模块。
1 | scss/ |
关于样式重置(Reset)
在 base/ 目录中,通常会有一个 _reset.scss 文件来统一不同浏览器的默认样式。手动编写和维护一个全面的 Reset 文件非常繁琐。因此,我们强烈推荐使用一个成熟的第三方库来完成这项工作。
推荐库:scss-reset
scss-reset 是一个优秀的现代化 CSS 重置库,它融合了 Meyer Reset、modern-css-reset 和 normalize.css 的优点,开箱即用。
安装它 (需要 Node.js 环境):
1
npm i scss-reset --save-dev
在主入口文件中使用它:
现在,我们来编写项目的主入口文件 scss/main.scss。它的职责就是作为项目“司令塔”,按正确的顺序编排和导入所有模块。
文件路径: scss/main.scss
1 | // 1. 导入第三方库和全局配置 |
如何使用模块?
现在,当我们在组件文件中编写样式时,就可以通过命名空间来安全地使用变量和 mixin 了。
示例: scss/components/_button.scss
1 | // 在 _button.scss 中,我们需要再次 @use 依赖的模块 |
这种基于 @use 和清晰文件结构的模块化工作流,清晰地分离了不同类型的样式,确保了模块之间的独立性和无冲突,是所有专业 SCSS 项目的基石。








