Sass/SCSS 预处理器:变量、混入与嵌套
初识 Sass/SCSS:CSS 的超级增强
在现代前端开发中,样式表的管理往往比 HTML 结构本身更为复杂。原生的 CSS 缺少变量、复用机制和层级组织能力,导致代码臃肿、维护困难。Sass (Syntactically Awesome Style Sheets) 正是为解决这些问题而生的 CSS 预处理器。它通过引入编程语言特性,让样式编写更高效、更易维护。本教程将聚焦 Sass 最核心的三大特性:变量、嵌套与混入,带你从零开始掌握这门利器。
安装与编译:让 Sass 运行起来
Sass 无法直接被浏览器解析,需要通过工具将 .scss 或 .sass 文件编译为标准的 .css 文件。推荐使用 npm 安装 Dart Sass(官方推荐版本):
npm install -g sass
编译单个文件:
sass style.scss style.css
监听文件变化并自动编译:
sass --watch input.scss:output.css
现在几乎所有现代构建工具(Webpack、Vite、Gulp)都内置了 Sass 支持,只需安装相应加载器即可无缝集成。接下来,我们深入三大基石特性。
变量:一次定义,全局复用
在原生 CSS 中,重复的颜色值、字体栈或间距数值散落在各处,一旦需要调整,不得不逐个查找替换。Sass 变量让你将这类值抽象为语义化的标识符。
定义与使用变量
变量以 $ 符号开头,赋值语法和 CSS 属性值一样:
// 定义变量
$primary-color: #3498db;
$font-stack: 'Helvetica Neue', sans-serif;
$base-padding: 1rem;
// 使用变量
body {
font-family: $font-stack;
color: $primary-color;
padding: $base-padding;
}
编译后:
body {
font-family: 'Helvetica Neue', sans-serif;
color: #3498db;
padding: 1rem;
}
变量作用域与默认值
Sass 的变量具有块级作用域,但可以通过 !global 声明提升为全局变量。还支持 !default 标记,表示“如果变量未被赋值则使用此默认值”,这对库开发和主题定制极其有用。
$border-radius: 3px !default;
.card {
$radius: 5px; // 局部变量
border-radius: $radius;
}
.footer {
border-radius: $border-radius;
}
数据类型与插值
Sass 变量不仅能存储颜色、长度,还支持数字、字符串、列表、映射(map)、布尔值等。在字符串中插入变量时,需使用 #{} 插值语法:
$side: left;
.alert-#{$side} {
border-#{$side}: 3px solid red;
}
编译后:
.alert-left {
border-left: 3px solid red;
}
合理运用变量,可以让整个样式系统的主题风格、间距、断点等高度统一,修改时只需改动一处。
嵌套:让选择器关系一目了然
CSS 依靠后代选择器来表现层级关系,但书写扁平的选择器无法直观反映 HTML 的嵌套结构。Sass 允许将选择器嵌套在父选择器内部,使代码结构更贴近 DOM 树。
基础选择器嵌套
.nav {
background: #333;
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: inline-block;
}
a {
color: white;
text-decoration: none;
}
}
编译为:
.nav { background: #333; }
.nav ul { list-style: none; margin: 0; padding: 0; }
.nav li { display: inline-block; }
.nav a { color: white; text-decoration: none; }
父选择器标识符 &
在嵌套中,借助 & 符号引用外层父选择器。这在编写伪类、伪元素或组合选择器时特别有用。
.button {
background: blue;
&:hover {
background: darkblue;
}
&.disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
编译后:
.button { background: blue; }
.button:hover { background: darkblue; }
.button.disabled { opacity: 0.5; cursor: not-allowed; }
& 还能巧妙地处理诸如 BEM 命名 或复合选择器:
.block {
&__element {
color: red;
}
&--modifier {
font-weight: bold;
}
}
输出 .block__element 和 .block--modifier,大幅减少重复的类名书写。
属性嵌套与占位符
除了选择器,Sass 还支持将命名空间属性(如 font-family, font-size)进行嵌套书写:
.box {
font: {
family: Arial;
size: 16px;
weight: bold;
}
margin: {
top: 20px;
bottom: 10px;
}
}
编译为常规的连字符属性,提升可读性。注意不要过度嵌套,通常推荐不超过 3 层深度,以保持编译后选择器的精炼。
混入:代码块的终极复用
变量适合存储单一值,而混入(Mixin)可以存储一堆样式规则,并且能接受参数,实现高阶复用。它适用于需要动态生成样式或跨多个选择器复用相同逻辑的场景(如清除浮动、媒体查询、主题皮肤)。
定义与使用无参混入
@mixin reset-list {
margin: 0;
padding: 0;
list-style: none;
}
.menu {
@include reset-list;
}
带参数的混入
参数让混入变得灵活,可以传入值来定制输出。参数支持默认值,调用时可传参或不传。
@mixin box-shadow($x, $y, $blur, $color: rgba(0,0,0,0.3)) {
box-shadow: $x $y $blur $color;
}
.card {
@include box-shadow(2px, 4px, 6px);
}
// 编译: box-shadow: 2px 4px 6px rgba(0,0,0,0.3);
.alert {
@include box-shadow(0, 0, 10px, red);
}
// 编译: box-shadow: 0 0 10px red;
关键字参数与可变参数
调用时可以使用关键字参数,顺序无关,提高可读性:
@include box-shadow($blur: 8px, $x: 1px, $y: 1px, $color: #ccc);
对于参数数量不确定的情况(如多个阴影或过渡值),用 ... 表示可变参数:
@mixin transitions($props...) {
transition: $props;
}
.btn {
@include transitions(color 0.3s, background 0.3s, opacity 0.2s);
}
混入中的内容块 @content
使用 @content 指令可以传递整个样式块到混入内部,常用来生成媒体查询包装器或响应式断点。
@mixin respond-to($media) {
@if $media == phone {
@media (max-width: 600px) { @content; }
} @else if $media == tablet {
@media (max-width: 900px) { @content; }
}
}
.profile {
width: 300px;
@include respond-to(phone) {
width: 100%;
}
}
编译后,.profile 的宽度在 600px 以下变为 100%。@content 让混入成为真正的“模板”,将控制逻辑与具体样式解耦。
变量、嵌套与混入协同实战
将三大特性结合,可以构建一套高度可维护的组件样式:
// 变量定义主题
$primary: #2ecc71;
$secondary: #27ae60;
$radius: 6px;
// 混入定义按钮基础
@mixin button-base($bg, $color: white) {
display: inline-block;
padding: 0.8em 1.5em;
border: none;
border-radius: $radius;
background: $bg;
color: $color;
text-decoration: none;
cursor: pointer;
// 嵌套的 hover 状态
&:hover {
background: darken($bg, 10%);
}
// 通过 @content 允许额外定制
@content;
}
.btn-primary {
@include button-base($primary) {
font-weight: bold;
text-transform: uppercase;
}
}
.btn-secondary {
@include button-base($secondary);
}
输出干净且结构清晰的 CSS,同时保留了极高的可调整性:修改一个变量即可切换主题色彩,调整混入或嵌套即可影响所有相关按钮。
延伸与最佳实践
- 避免选择器过深:嵌套是双刃剑,超过 3 层往往导致特异性过高和难以覆盖,参考 BEM 等命名约定来保持扁平。
- 模块化组织:将变量、混入、通用样式拆分为
_variables.scss、_mixins.scss、_base.scss等部分文件(Partial),通过@use或@import加载,提升协作效率。 - 善用内置函数:Sass 提供了颜色运算、数学计算、列表处理等大量函数(如
darken(),lighten(),rgba(),nth()),与变量结合能动态生成丰富的样式。 - 谨慎使用混入 vs 占位符
%:当混入不接收参数且生成完全相同的静态代码时,使用@extend配合占位符选择器可以避免重复的 CSS 输出,减少文件体积。
掌握了变量、嵌套和混入,你已经拥有了将 CSS 转变为可编程样式系统的能力。从个人项目到大型团队协作,Sass 都能显著提升开发体验,让你的样式表成为逻辑清晰、易于迭代的工程资产。