跳到主要内容

SCSS

如果只从现代前端项目的普及度看,SCSS 仍然是最常见的 CSS 预处理器。

原因不复杂:它既保留了接近 CSS 的语法,又把变量、嵌套、模块化、函数、循环这些能力补得比较完整。放到 React、Vue、Vite、Webpack 这条主线里,也几乎没有明显阻力。

SCSS 和 Sass 的关系

这一点经常容易混。

  • Sass 是整个预处理器体系的名字
  • SCSS 是 Sass 提供的一种语法
  • 还有一种更老的缩进式语法,通常叫 Sass indented syntax

现在日常开发里说“用 Sass”,很多时候其实指的是“写 SCSS”。

SCSS 最常见的特性

1. 变量

SCSS 用 $ 声明变量。

$brand-color: #0ea5e9;
$radius-base: 14px;
$space-base: 8px;

.card {
border-radius: $radius-base;
padding: $space-base * 2;
color: $brand-color;
}

这层最适合先收:

  • 颜色
  • 间距
  • 圆角
  • 字号
  • z-index

2. 嵌套

.header {
display: flex;

.nav {
display: flex;
gap: 16px;

a {
color: #111827;

&:hover {
color: $brand-color;
}
}
}
}

嵌套是 SCSS 最常被使用的能力之一,但也最容易写过头。层级越深,最后产出的选择器越重。

3. 混入(Mixin)

@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}

.modal {
@include flex-center;
}

4. 参数化混入

@mixin button-size($height, $padding-x) {
height: $height;
padding: 0 $padding-x;
}

.button-sm {
@include button-size(32px, 12px);
}

.button-lg {
@include button-size(44px, 20px);
}

这层很适合设计系统组件。

5. 占位符与 @extend

%panel-base {
border-radius: 16px;
background: #fff;
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
}

.card {
@extend %panel-base;
padding: 24px;
}

.dialog {
@extend %panel-base;
padding: 32px;
}

@extend 有时能减少重复,但复杂项目里也容易让选择器组合变难读,所以很多团队会更偏向 mixin。

6. 运算

$gap: 8px;

.grid {
gap: $gap * 2;
padding: $gap * 3;
}

7. 函数

$brand-color: #0ea5e9;

.button {
background: $brand-color;
}

.button:hover {
background: darken($brand-color, 8%);
}

除了内置颜色函数,也能自定义函数。

@function px-to-rem($px, $base: 16px) {
@return ($px / $base) * 1rem;
}

.title {
font-size: px-to-rem(24px);
}

8. 条件与循环

@for $i from 1 through 4 {
.mt-#{$i} {
margin-top: $i * 4px;
}
}
$colors: (
primary: #2563eb,
success: #16a34a,
danger: #dc2626,
);

@each $name, $color in $colors {
.text-#{$name} {
color: $color;
}
}

这类写法适合:

  • spacing utilities
  • 颜色变体
  • 状态类名

9. 模块化

旧项目常见 @import,现在 Sass 官方更推荐 @use@forward

// _tokens.scss
$brand-color: #2563eb;
$radius-base: 12px;
// button.scss
@use './tokens' as *;

.button {
background: $brand-color;
border-radius: $radius-base;
}

这一层是现代 SCSS 很关键的变化。

在前端项目里怎么集成

Vite

pnpm add -D sass

Vite 会直接识别 .scss.sass

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "./src/styles/tokens.scss" as *;`,
},
},
},
})

Webpack

pnpm add -D sass sass-loader css-loader style-loader
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
}

Vue SFC

<style lang="scss" scoped>
.card {
padding: 16px;

.title {
font-weight: 600;
}
}
</style>

这类写法在 Vue 项目里一直很常见。

SCSS 在真实项目里最常见怎么用

1. token 文件

$color-primary: #2563eb;
$color-text: #111827;
$space-2: 8px;
$space-3: 12px;
$radius-md: 12px;

2. mixin 文件

@mixin line-clamp($lines) {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}

3. 通用函数

@function px-to-rem($px, $base: 16px) {
@return ($px / $base) * 1rem;
}

4. 页面或组件局部样式

SCSS 常见的价值,不是替代所有样式方案,而是在:

  • 局部复杂组件
  • 设计系统底层
  • 样式复用较多的场景

会更顺手。

SCSS 的优点

  • 语法接近 CSS
  • 生态最成熟
  • @use / @forward 比较适合大型项目
  • 在现代构建链里兼容度高

SCSS 的局限

  • 嵌套容易写重
  • 循环和 mixin 一多,样式逻辑会变复杂
  • 现在很多 token 和主题能力,也可能直接交给 CSS variables 完成

现在还值不值得在新项目里用

值,但要分场景。

值得用的情况

  • 样式复用很多
  • 组件库或设计系统层需要函数、mixin、模块化
  • 团队已经有成熟 SCSS 经验

也可以不急着用的情况

  • 项目已经全面走 Tailwind
  • CSS variables 足够解决 token 和主题问题
  • 组件局部样式不复杂

所以现在的常见局面不是“所有项目都该上 SCSS”,而是“SCSS 仍然是一套很稳的工具,只是需要按场景使用”。

和 Less、Stylus 的区别,先记住这些

  • 和 Less 比:SCSS 生态更强,模块化更完整
  • 和 Stylus 比:SCSS 更接近 CSS,团队协作成本更低
  • 放到现代前端项目里,SCSS 的默认接受度更高