语法基础:变量、嵌套与运算
本文覆盖 Sass 日常使用最频繁的四类语法:变量、嵌套、运算、注释。概念与安装见 Sass 简介;复用机制(Mixin/继承)见 复用机制;模块与控制流见 模块与控制流。
一、变量
Sass 变量存储可复用值(颜色、字号、间距等),使用 $ 声明,编译为 CSS 中的具体值。模块化组织见 模块与控制流。
1. 基本语法
// 声明变量
$primary-color: #3498db;
$font-size-base: 16px;
$border-radius: 4px;
// 使用变量
.button {
background-color: $primary-color;
font-size: $font-size-base;
border-radius: $border-radius;
}
编译后的 CSS:
.button {
background-color: #3498db;
font-size: 16px;
border-radius: 4px;
}
2. 作用域
- 全局变量:在选择器外部声明,可在任何地方使用。
- 局部变量:在选择器或函数内部声明,仅在该作用域内有效。
$global-color: #333; // 全局变量
.container {
$local-color: red; // 局部变量(仅在此块内有效)
color: $local-color;
background: $global-color; // ✅ 可访问全局变量
}
// 强制修改全局变量(慎用)
.content {
$global-color: black !global; // 将局部修改提升为全局
color: $global-color; // 使用修改后的全局变量
}
// 错误:$local-color 在此处未定义
// .footer { color: $local-color; }
最佳实践:避免滥用
!global,通常通过变量文件(如_variables.scss)统一管理全局变量,保持作用域清晰。
3. 默认值 !default
!default 用于为变量指定默认值:如果该变量之前已经被赋值,则使用已有值;否则使用默认值。常用于可配置的组件库。
// _theme.scss
$theme-color: blue !default;
// main.scss(@use 时通过 with 覆盖)
@use "theme" with (
$theme-color: red,
);
.button {
background: theme.$theme-color;
}
4. 数据类型
Sass 支持 6 种主要数据类型:
| 类型 | 示例 | 说明 |
|---|---|---|
| 数字(Numbers) | 10, 10px, 10%, 10deg | 可带或不带单位 |
| 字符串(Strings) | "微软雅黑", sans-serif, 'Helvetica' | 可有引号或无引号 |
| 布尔值(Booleans) | true, false | 用于条件判断 |
| 颜色(Colors) | #FF00FF, rgb(255,0,255), hsl(360,50%,50%) | 多种表示法 |
| 列表(Lists) | 10px 20px 30px(空格分隔)Arial, Helvetica, sans-serif(逗号分隔) | 类似数组 |
| Map 映射 | (key1: value1, key2: value2) | 键值对集合 |
| 空值(Null) | null | 未定义或缺失值 |
$font-stack: "Helvetica", sans-serif; // 列表
$breakpoints: (
// Map
small: 576px,
medium: 768px,
large: 992px
);
$border-style: solid; // 字符串
$is-dark-mode: false; // 布尔值
5. 变量插值 #{}
在某些位置(如选择器名称、属性名称、字符串中),直接使用 $变量名 无效,必须使用插值语法 #{$变量名} 将变量的值嵌入为字符串的一部分。
$dir: "left";
$version: "v1";
$font-name: "Roboto";
// 1. 用在属性名中
margin-#{$dir}: 10px; // 编译为:margin-left: 10px;
// 2. 用在选择器名称中(动态构造类名)
.alert-#{$version} {
color: red;
}
// 编译后:.alert-v1 { color: red; }
// 3. 用在字符串中(如 @font-face 的 url)
@font-face {
font-family: #{$font-name};
src: url("/fonts/#{$font-name}.woff2");
}
// 4. 用在注释中
/* 当前版本: #{$version} */
注意:插值
#{}不能用于数字运算,它只是纯文本替换。例如#{$size}px可以拼接带单位的数字,但$size本身必须是数字。
变量小结
- 声明:
$name: value;;插值:#{$name}用于选择器名、属性名等。 - 作用域:局部优先;慎用
!global。 - 配置:
!default配合@use ... with (...)。
二、嵌套
Sass 嵌套用于表达 DOM 层级,减少重复父选择器。建议不超过 3 层,避免生成过长选择器。现代原生 CSS 嵌套(&)在浏览器中已可用,语法与 SCSS 相近,详见本文第四节。
1. 选择器嵌套
.nav {
ul {
margin: 0;
li {
display: inline-block;
a {
color: $primary-color;
}
}
}
}
编译后的 CSS:
.nav ul {
margin: 0;
}
.nav ul li {
display: inline-block;
}
.nav ul li a {
color: #3498db;
}
最佳实践:嵌套层级不超过 3 层,避免生成过于冗长的 CSS 选择器,保持性能。
2. 父选择器引用 &
& 符号表示嵌套规则的外层父选择器,用于在嵌套内部引用父级选择器的名称,特别适用于伪类、伪元素、BEM 修饰符等场景。
.button {
background: blue;
&:hover {
// 编译为 .button:hover
background: darkblue;
}
&::before {
// 编译为 .button::before
content: "→";
}
&--primary {
// BEM 命名法,编译为 .button--primary
background: green;
}
}
多个 & 连用(表示并列的多个父级选择器):
.side {
.widget & {
// 编译为 .widget .side
color: red;
}
}
注意:
&展开时是完整解析过的父选择器序列(包含空格),而不是简单的字符串拼接。
3. 属性嵌套
对于具有相同命名空间(如 border-*、font-*、margin-* 等)的属性,可以使用属性嵌套来简化编写。
.box {
border: {
top: 1px solid red;
bottom: 2px dashed blue;
}
}
// 编译为:
// .box { border-top: 1px solid red; border-bottom: 2px dashed blue; }
也支持缩写与展开混用:
font: {
family: "Arial";
size: 16px;
weight: bold;
}
// 编译为:font-family: "Arial"; font-size: 16px; font-weight: bold;
4. @at-root 指令
@at-root 指令可以让当前选择器跳出所有祖先选择器的嵌套,直接回到根选择器层级。这在重构代码或需要生成独立于父级的规则时非常有用。
.parent {
color: blue;
@at-root .child {
color: red; // 编译为独立的 .child 选择器,而非 .parent .child
}
}
编译结果:
.parent {
color: blue;
}
.child {
color: red;
}
带参数 with / without(高级用法):
@at-root (without: all) { ... } // 跳出所有层级(包括媒体查询等)
@at-root (with: media) { ... } // 仅保留媒体查询层,跳出其他
典型应用场景:生成工具类(全局样式)、将部分样式从深层嵌套中“解放”出来、更好地配合 BEM 或 utility-first 框架。
嵌套小结
| 特性 | 语法 | 用途 |
|---|---|---|
| 选择器嵌套 | 父 { 子 { } } | 表达层级,减少重复 |
父选择器引用 & | &:hover、&--modifier | 伪类、伪元素、BEM 修饰符 |
| 属性嵌套 | border: { top: ...; } | 简化同一命名空间的属性 |
@at-root | @at-root .selector | 跳出当前嵌套,回到根层级 |
合理利用嵌套可以让样式更清晰;层级宜浅,并关注编译后选择器权重。
三、运算
Sass 支持数学、颜色与字符串运算;需注意数据类型、单位兼容性及除法应使用 sass:math 的 math.div()。
1. 数学运算
Sass 支持标准的加(+)、减(-)、乘(*)运算,以及除法(推荐使用 math.div() 函数)。
@use "sass:math";
$base: 16px;
.box {
width: 100% / 3; // 算术除法(仅当 / 在表达式中有意义时,不推荐)
padding: $base * 2; // 32px
margin: $base + 10px; // 26px
line-height: math.div(24px, $base); // 1.5(无单位纯数字)
}
除法运算的特别注意
- 旧语法:使用
/作为除法运算符(如width: 100% / 3;)。 - 问题:在 CSS 原生语法中,
/有多种含义(如font: 12px/14px表示字号/行高)。为消除歧义,Dart Sass 自 2.0 起已将孤立/标记为过时。 - 推荐做法:始终使用
math.div()函数执行除法,避免使用/。
// ❌ 不推荐(会触发警告)
$ratio: 100% / 3;
// ✅ 推荐
@use "sass:math";
$ratio: math.div(100%, 3);
2. 单位规则
Sass 的数学运算遵循“单位代数”规则:
- 相同单位的量可以加减乘除,结果保留单位(如
10px + 5px = 15px)。 - 不同单位的量在加减时会尝试转换,但若转换不合理(如
10px + 2em),Sass 会抛出编译错误,因为em相对于父元素的px值在编译期无法确定。 - 乘法:单位会相乘(如
5in * 5in = 25in²),但 CSS 不支持平方英寸单位,通常应避免。 - 推荐做法:在进行复杂计算前,先用
math.div()剥离单位,得到纯数字,计算完后再恢复所需单位。
@use "sass:math";
$value-with-unit: 24px;
$unitless: math.div($value-with-unit, 1px); // 24(无单位)
3. 颜色运算
Sass 支持对颜色值进行通道运算(RGB 每个通道分别计算)。注意:颜色运算不如 color 模块的函数精确,推荐使用内置颜色函数。
$base-color: #036; // 相当于 rgb(0, 51, 102)
.darken {
// 颜色通道相加:rgb(0+34, 51+34, 102+34) = rgb(34,85,136) → #225588
background: $base-color + #222;
}
更常用的颜色调整方式(推荐):
@use "sass:color";
.lighten {
background: color.scale($base-color, $lightness: 20%);
}
4. 字符串运算
使用 + 运算符可以拼接字符串。注意:如果第一个操作数是带引号的字符串,结果也会带引号;否则结果无引号。
$prefix: "icon-";
.icon {
&::before {
content: $prefix + "home"; // 输出 "icon-home"
}
}
$font-family: "Helvetica" + ", " + Arial; // 结果为 "Helvetica, Arial"(自动补引号)
插值替代:在更复杂的字符串构建中,可以使用 #{} 插值。
运算小结
| 运算类型 | 注意事项 |
|---|---|
| 数学运算 | 除法使用 math.div();避免直接使用 /;相同单位可运算,不同单位加减需谨慎 |
| 单位规则 | 乘积会产生复合单位,通常应避免;复杂运算先剥离单位 |
| 颜色运算 | 通道加减,但推荐使用 color 模块函数 |
| 字符串运算 | 使用 + 拼接;引号继承规则需留意 |
四、注释与原生 CSS 嵌套
1. 注释语法
Sass 支持三种注释语法,区别在于是否被保留到编译后的 CSS 文件中。
| 注释语法 | 说明 | 编译后是否保留 |
|---|---|---|
/* 内容 */ | 标准 CSS 多行注释 | ✅ 保留 |
// 内容 | 单行注释(Sass 独有) | ❌ 不保留 |
/*! 内容 */ | 重要注释(通常用于版权声明) | ✅ 保留(即使压缩模式下也会保留) |
// 以下是主题色变量——此注释在编译后会消失
$primary: #3498db;
/* 模块化CSS样式 */
.button {
background: $primary;
}
/*! 版权声明:© 2026 MyCompany */
编译后的 CSS:
/* 模块化CSS样式 */
.button {
background: #3498db;
}
/*! 版权声明:© 2026 MyCompany */
使用建议:
- 调试阶段可使用
//注释辅助说明,不影响输出。 - 需要保留在 CSS 中的说明(如模块说明、许可证)使用
/* ... */。 - 版权等重要声明使用
/*! ... */,确保即使开启--style=compressed也不会被移除。
2. 与原生 CSS 嵌套的关系
CSS 嵌套选择器 已在主流浏览器中实现(具体版本见 MDN 兼容性表)。语法与 SCSS 嵌套相似,但不包含 Sass 的变量、混入、控制指令等编译期能力。
相同点:& 父级引用
原生 CSS 也支持使用 & 符号引用父选择器,用法与 Sass 基本一致。
/* 原生 CSS 嵌套 */
.button {
background: blue;
&:hover {
background: darkblue;
}
}
主要限制与差异
| 特性 | Sass 嵌套 | 原生 CSS 嵌套 |
|---|---|---|
| 选择器拼接方式 | 默认使用空格后结合(后代选择器) | 同 Sass(空格表示后代) |
串联选择器(如 .a.b) | 可写作 &.b | 同样支持 &.b |
| 嵌套深度 | 无语法上限(工程上建议控制在较浅层级) | 无语法上限;过深选择器会增加匹配成本 |
在 @media 等规则内嵌套 | 支持 | 支持(见 MDN 嵌套与 at-rule 说明) |
& 后直接跟类名 | 支持(如 &.active) | 支持 |
& 后跟复杂选择器(如 & > .child) | 支持 | 支持 |
| 后代嵌套(子规则以类型/类开头) | .parent { .child { } } → .parent .child | 同左(见 MDN 嵌套规则) |
| 对无效选择器的错误提示 | 编译时报错 | 浏览器解析时忽略无效规则 |
实际开发建议
- 需要变量、混入、
@use模块等:继续使用 SCSS 编译为普通 CSS,与目标浏览器是否支持原生嵌套无关。 - 仅使用嵌套、且目标环境已支持原生嵌套:可直接写 CSS 嵌套;发布前对照 MDN 兼容性表与项目最低浏览器要求。
- 通用建议:控制嵌套深度,避免选择器过长;需要拼接父选择器时使用
&(与规范一致)。
总结
- 注释:根据需要选择合适的语法,
/*! */用于版权声明,//仅开发使用。 - 嵌套:在需编译链路的项目中 SCSS 嵌套仍常用;若仅面向现代浏览器,可评估 原生 CSS 嵌套 是否满足需求。
- 变量与运算是 Sass 最基础的两块能力,配合 模块与控制流 中的内置函数可完成绝大多数样式计算。
参考文献
| 资料 | 说明 |
|---|---|
| Sass:Variables | 变量与作用域(英文) |
| Sass:Interpolation | #{} 插值 |
| Sass:Nesting | 嵌套规则(英文) |
| Sass:Operators | 运算符 |
| Sass:sass:math | math.div 等 |
| Sass:Comments | 注释语法 |
| MDN:CSS 嵌套 | 原生嵌套 |
相关文章
Sass 简介与安装
Sass(Syntactically Awesome Style Sheets)是 CSS 预处理器,在 CSS 语法上增加变量、嵌套、混合、模块、控制指令等;有 SCSS 与缩进语法两种源码语法,官方实现为 Dart Sass。
模块与控制流:@use、内置函数、@if/@for/@each
Dart Sass 推荐用 @use/@forward 替代已弃用的 @import;内置 sass:* 模块提供颜色、字符串、列表、Map、数学等函数;@if/@for/@each/@while 用于条件与循环生成样式。
复用机制:Mixin 与继承
Mixin(@mixin/@include)支持参数与 @content,适合动态样式;@extend 与 %placeholder 通过合并选择器复用完全相同的静态样式,减少 CSS 体积。
Less 基础与核心语法
Less 是 JavaScript 实现的 CSS 预处理器,在 CSS 语法上扩展变量(@)、嵌套、混合、运算与函数,编译为普通 CSS 后由浏览器加载;本文覆盖安装、CLI、构建工具集成与全部核心语法。
颜色与背景
color 设置前景(多为文字)色;background-* 设置元素背景(颜色、图像、渐变)。二者共同决定对比度与视觉层次,直接影响 无障碍 阅读体验。排版中的文本颜色用法见 排版与文本。
工程化集成与扩展
Less 可集成到 Vite、Webpack、Vue CLI 等工具链,实现编译、全局变量注入与路径处理。
Series
sass
4 / 4