Sass
Sass(Syntactically Awesome Stylesheets)是一种把脚本特性引入层叠样式表的样式表语言,也是最早的 CSS 预处理器之一。它在 CSS 之上提供变量、嵌套规则、混入、函数与继承等写法,再由编译器转换成浏览器可直接解析的普通 CSS 文件[1]。Sass 最初用 Ruby 编写,现有 .sass 缩进式与 .scss 块式两套语法,目前由 Dart Sass 作为官方维护实现。
定义
Sass 是一种先编译、后交付的样式表语言,本身不是浏览器能直接识别的格式。开发者用 Sass 语法书写样式规则,再由 Sass 编译器输出标准 CSS 文件供网页引用[2]。它与 LESS、Stylus 同属 CSS 预处理器的常见选择,其中出现时间最早[3]。
Sass 的语法分两支。较早的一支称为缩进语法,借缩进划分代码块、用换行分隔规则,思路取自 Haml;较晚的一支称为 SCSS(Sassy CSS),沿用 CSS 的大括号与分号,合法的 CSS 在 SCSS 中同样合法[2]。两者通常分别对应 .sass 与 .scss 两种文件扩展名,日常语境中的 Sass 一般泛指包含 SCSS 在内的整门语言[1]。
语言层面的脚本部分被称为 SassScript,它是解释器读取并展开的动态类型脚本语言,变量、嵌套、混入与选择器继承都由它提供[2]。整套项目采用 MIT 许可证开放源代码[1]。
原理
Sass 的工作可以概括为编译期的文本变换:编译器读取 .sass 或 .scss 源文件,把其中的脚本结构展开,再生成选择器与声明构成的普通 CSS[2]。命令行工具也可以监视源文件,每次保存后重新输出 CSS,省去手工触发的步骤[2]。编译结果默认附带源映射文件,调试工具据此把生成样式回溯到原始源文件的行号[4]。
变量是 SassScript 最基本的构件,以 $ 开头命名,可在属性值、函数参数与返回值中出现;编译时变量被替换为具体取值,因此它只存在于源文件中,不会随 CSS 一起到达浏览器[1]。这一特征使 Sass 变量与浏览器运行时生效的 CSS 自定义属性形成分野,后者可以在页面加载后被修改[5]。
嵌套规则让选择器按 HTML 结构层层书写,减少重复书写父级选择器;块内可用 & 引用父选择器,属性也可以按命名空间折叠书写[1]。混入(mixin)把一段可复用的声明封装起来,调用时展开为完整代码,相当于带参数的宏;选择器继承(@extend)则把共用样式的选择器合并输出,二者的差别在于前者会产生多份重复声明,后者把选择器组合在一起[6]。
模块化依赖由 at 规则完成。早期用 @import 载入其他文件,所有成员进入同一全局命名空间;2019 年引入的模块系统改用 @use 与 @forward,每个模块默认带命名空间且只加载一次,可以避免命名冲突和重复输出的 CSS[7]。
flowchart LR
A[.scss / .sass 源文件] --> B[SassScript 解析]
B --> C[变量与嵌套展开]
C --> D[混入、继承、函数求值]
D --> E[生成 CSS]
E --> F[源映射 .css.map]
发展历程
Sass 于 2006 年由 Hampton Catlin 设计、Natalie Weizenbaum 开发,当时 Ruby 是网页开发的主流语言,二人已用它实现 Haml 模板语言,因此首版实现也选择 Ruby。此后 Weizenbaum 与 Chris Eppstein 继续以 SassScript 扩充语言能力[2]。
缩进语法虽然精简,却不兼容已有的 CSS 写法,这使 Sass 在早期推广上落后于后来出现、直接沿用 CSS 语法的 LESS[3]。Sass 随后吸收这一经验,推出大括号加分号的写法,即 SCSS,自第 3 代版本起支持,并保持对普通 CSS 的向下兼容[8]。
2012 年的 HTML5 开发者大会上,Catlin 公布了 libSass 1.0,这是由他、Aaron Leung 与 Moovweb 团队用 C++ 编写的开源实现,目标是与 Ruby 版本完全兼容,并便于嵌入 Node、Go、Ruby 等环境[2]。
2016 年 10 月,Weizenbaum 宣布用 Dart 重写的新实现 Dart Sass,理由是 Ruby 版本对大样式表偏慢,而 C++ 版本添加语言特性困难[9]。Dart Sass 的 1.0.0 稳定版于 2018 年 3 月 26 日发布,兼容 sass-spec 定义的语言规范,并在 npm、Chocolatey、Homebrew 等渠道分发[10]。
Ruby Sass 已于 2019 年 3 月 26 日停止生命周期,官方建议使用者迁移到其他实现。2022 年 Sass 团队宣布弃用 libSass 以及建立在其上的 Node Sass,新项目改用 Dart Sass[11]。从 Dart Sass 1.80.0 起,@import 规则与全局内置函数被标记弃用,预计在 Dart Sass 3.0.0 中移除[4]。
应用
Sass 主要面向样式表规模较大、需要多人协作的前端项目,变量适合统一管理全站的颜色、字号等设计取值,改动一处即可影响所有引用点[8]。组件化开发中,嵌套规则与混入便于把样式按结构组织,部分文件(文件名以下划线开头的 partial)则用于拆分出可复用的片段[6]。
编译入口有多种形式:独立可执行文件适合命令行直接调用,npm 上的 sass 包可作为 JavaScript 库在构建流程中调用,也可通过 sass-embedded 以子进程和消息传递的方式被其他语言集成[11]。前端构建工具因此能把 Sass 编译并入打包步骤[12]。
局限
浏览器至今没有内置对 Sass 的支持,变量、混入、@use 与缩进语法都只在源文件中存在,交付前必须经过编译,页面本身拿到的只能是普通 CSS[13]。与运行时生效的 CSS 自定义属性相比,Sass 变量的取值在编译结束时就已固定,无法在浏览器中随主题切换而改变[5]。
混入被重复调用时会把同一段声明多次输出,继承则无论是否被使用都会保留基类样式,滥用两者都会让最终 CSS 体积膨胀,过深的嵌套也会生成层级过长的选择器[6]。
@import 的全局命名空间曾长期困扰大型项目,也使工具难以判断某个变量或混入的来源;改用模块系统需要同步调整既有代码,官方为此提供了 sass-migrator 迁移工具[4]。此外,libSass 长期未跟进新语言特性,使用旧实现的项目可能无法编译依赖新语法的样式表[11]。
参见
参考资料
- Sass [引用日期2026-10-29]
- Sass (style sheet language) [引用日期2026-10-29]
- CSS 预编译语言 Sass、Scss、Less 和 Stylus [引用日期2026-10-29]
- Breaking Change: @import and global built-in functions [引用日期2026-10-29]
- Breaking Change: CSS Variable Syntax [引用日期2026-10-29]
- Sass带来的变革 [引用日期2026-10-29]
- `@import` is Deprecated [引用日期2026-10-29]
- CSS预处理器入门:Sass/SCSS的实用指南 [引用日期2026-10-29]
- Announcing Dart Sass [引用日期2026-10-29]
- Dart Sass 1.0.0 已发布 [引用日期2026-10-29]
- Node Sass 弃用,以 Dart Sass 代替 [引用日期2026-10-29]
- A [Dart][dart] implementation of [Sass][sass] [引用日期2026-10-29]
- Compilation [引用日期2026-10-29]