源本科技 | 码上会

CSS 预处理器

2026/03/06
16
0

为什么需要预处理器

在现代前端开发中,随着项目规模的日益复杂,传统的 CSS(层叠样式表)逐渐显露出其局限性。CSS 本质上是一种声明式的标记语言,缺乏变量、嵌套、逻辑判断、循环等编程特性。这导致在大型项目中,样式表容易出现以下痛点:

  • 代码冗余:相同的颜色值、字体栈或媒体查询在多处重复书写。

  • 维护困难:修改一个全局主题色需要手动查找并替换数十甚至上百处。

  • 结构松散:难以直观地反映 HTML 的层级结构,选择器命名容易冲突。

  • 缺乏复用:无法像函数一样封装通用的样式块。

为了解决这些问题,CSS 预处理器应运而生。它们是一种特殊的脚本语言,通过扩展 CSS 的功能,引入了变量、嵌套、混入(Mixin)、继承、函数运算等编程概念。开发者使用预处理语言编写样式,然后通过编译工具将其转换为浏览器能够识别的标准 CSS 文件。

在众多预处理器中,SASS(Syntactically Awesome Stylesheets)和LESS(Leaner Style Sheets)是影响力最广、使用率最高的两大巨头。虽然它们的目标一致——让 CSS 编写更高效、灵活且易于管理,但在语法设计、功能深度、编译机制及生态系统上各有千秋。本文将深入剖析这两者,帮助开发者做出最适合的技术选型。


SASS

功能强大的工业级标准

1. 概述与历史演变

SASS 诞生于2007 年,由 Hampton Catlin 设计,最初基于 Ruby 语言开发,是最早出现的 CSS 预处理器。它的核心理念是将编程逻辑引入样式表,赋予 CSS“超能力”。

SASS 发展至今,主要存在两套语法体系:

  • 缩进语法(.sass):这是 SASS 的原始语法。它严格依赖缩进来表示层级,省略了花括号 {} 和分号 ;,风格酷似 Python。虽然极致简洁,但由于对缩进敏感且与标准 CSS 差异较大,目前使用率已大幅降低。

  • SCSS 语法(.scss):全称 Sassy CSS,于 SASS 3.0 版本引入。它是 CSS3 语法的超集,意味着任何合法的 CSS 代码都是合法的 SCSS 代码。它保留了花括号和分号,极大降低了学习门槛,是目前社区绝对的主流选择。

注意:目前官方推荐的编译器是 Dart Sass,它取代了早期的 Ruby Sass 和 Node-Sass(已废弃),提供了更好的性能和兼容性。

2. 核心特性深度解析

(1) 变量

使用 $ 符号定义变量,用于存储颜色、字体、尺寸等任意 CSS 值。这不仅实现了“一次定义,处处使用”,还让主题切换变得轻而易举。

$primary-color: #3498db;
$font-stack: 'Helvetica Neue', Helvetica, Arial, sans-serif;
$base-spacing: 16px;

body {
  font-family: $font-stack;
  color: $primary-color;
  margin: $base-spacing;
}

(2) 嵌套

允许在选择器内部嵌套子选择器,直观地反映 HTML 文档树结构,减少父选择器的重复书写,提升代码可读性。

nav {
  background: #333;
  
  ul {
    list-style: none;
    padding: 0;
    
    li {
      display: inline-block;
      
      a {
        color: white;
        text-decoration: none;
        
        &:hover { // & 引用父选择器
          text-decoration: underline;
        }
      }
    }
  }
}

(3) 混入

通过 @mixin 定义可复用的样式代码块,并使用 @include 调用。Mixin 支持参数传递和默认值,是构建组件化样式的基石。

@mixin flex-center($direction: row) {
  display: flex;
  flex-direction: $direction;
  justify-content: center;
  align-items: center;
}

.container {
  @include flex-center; // 使用默认值
}

.sidebar {
  @include flex-center(column); // 传入参数
}

(4) 继承

使用 @extend 指令,让一个选择器继承另一个选择器的所有样式。这在生成大量具有共同基础样式的类时非常有用,能有效减少生成的 CSS 文件大小(通过组合选择器实现)。

%message-base { // 占位符选择器,不会单独编译输出
  border: 1px solid #ccc;
  padding: 10px;
  font-size: 14px;
}

.success {
  @extend %message-base;
  border-color: green;
  color: green;
}

.error {
  @extend %message-base;
  border-color: red;
  color: red;
}

(5) 运算与内置函数

SASS 支持标准的数学运算(加减乘除),并拥有极其丰富的内置函数库,特别是在颜色处理(如 lighten(), darken(), rgba(), complement())和列表 / 地图操作方面表现卓越。

(6) 高级编程逻辑

这是 SASS 区别于 LESS 的最大亮点。SASS 提供了图灵完备的逻辑控制指令,使其不仅仅是一个样式工具,更像一门编程语言:

  • 条件判断@if, @else if, @else

  • 循环控制@for (计数循环), @each (遍历列表 /Map), @while

  • 自定义函数:通过 @function 定义返回值的函数,可用于复杂的计算逻辑。

案例:使用循环自动生成栅格系统

@for $i from 1 through 12 {
  .col-#{$i} {
    width: (100% / 12) * $i;
  }
}

(7) 模块化系统

SASS 鼓励将样式拆分为多个片段文件(Partials,文件名以下划线开头,如 _variables.scss)。现代 SASS 推荐使用 @use@forward 替代旧的 @import,以提供更好的命名空间管理和避免重复加载。


LESS

轻量灵活的快速开发利器

1. 概述与设计哲学

LESS 由 Alexis Sellier 于2009 年设计。最初用 Ruby 编写,但很快被移植到JavaScript环境中。这一转变赋予了 LESS 独特的优势:它可以在服务端(Node.js)编译,也可以在客户端(浏览器)直接运行

LESS 的设计哲学是“保持简单”,尽可能贴近原生 CSS 语法,旨在让开发者以最小的认知成本平滑过渡。

2. 核心特性深度解析

(1) 变量

与 SASS 不同,LESS 使用 @ 符号定义变量。其作用域规则遵循“就近原则”和“惰性加载”(变量可以先使用后定义)。

@primary-color: #3498db;
@font-stack: 'Helvetica Neue', sans-serif;

body {
  font-family: @font-stack;
  color: @primary-color;
}

(2) 混入

LESS 的 Mixin 定义更加直观,可以直接将类选择器当作 Mixin 使用。调用时只需加上括号即可。

.border-radius(@radius: 4px) {
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
  border-radius: @radius;
}

.box {
  .border-radius(10px); // 调用
}

// 也可以直接混入一个类的所有样式
.button-base {
  padding: 10px 20px;
  color: white;
}

.submit-btn {
  .button-base(); 
  background: green;
}

(3) 嵌套与父选择器

同样支持嵌套和 & 符号引用父元素,常用于伪类和伪元素的处理。

a {
  color: blue;
  &:hover {
    color: red;
  }
  &::before {
    content: "🔗";
  }
}

(4) 运算与函数

支持基本的数学运算和内置函数(颜色运算、字符串操作等)。虽然函数库不如 SASS 丰富,但覆盖了日常开发的 90% 需求。

(5) 守卫与命名空间

LESS 没有完整的 if/else 语句,但提供了守卫(Guard)机制(类似 when 关键字)来实现简单的条件混合。此外,LESS 支持将变量和 Mixin 封装在类或 ID 中形成命名空间,有效防止全局污染。

.mixin (@a) when (@a > 10) {
  width: 100%;
}
.mixin (@a) when (@a =< 10) {
  width: 50%;
}

(6) 客户端编译特性

这是 LESS 独有的“杀手锏”。在开发阶段,只需在 HTML 中引入 less.js,即可直接在浏览器中实时编译 .less 文件。这对于没有后端构建环境的前端原型演示、CMS 主题在线编辑等场景非常友好(注:生产环境仍推荐服务端编译以提升性能)。


对比分析

为了更直观地展示两者的差异,我们从多个维度进行对比:

对比维度

SASS (SCSS)

LESS

变量符号

$ (美元符号)

@ (At 符号,需注意与 CSS @media 等区分 )

语法兼容性

SCSS 是 CSS 超集,兼容性好;原始 SASS 语法差异大

完全兼容 CSS,任何 CSS 都是合法的 LESS

编译环境

主要依赖 Dart Sass (Node.js 环境),需构建工具链

基于 JavaScript,支持 Node.js 服务端浏览器客户端 编译

逻辑控制

强大。支持完整的 @if, @for, @each, @while 循环及自定义函数

有限。主要通过 Mixin 守卫 (when) 实现条件判断,缺乏原生的循环语句

功能深度

图灵完备,适合构建复杂的样式系统和设计令牌(Design Tokens)

聚焦核心功能,简洁实用,适合常规业务开发

生态系统

统治级地位。Bootstrap 4/5, Foundation, Bulma, Tailwind (源码) 等均基于 SASS

曾经流行(Bootstrap 2/3),目前社区活跃度下降,新项目采用率较低

学习曲线

中等。需掌握较多编程概念和特殊语法

低。几乎零门槛,CSS 开发者可直接上手

典型应用场景

大型企业应用、UI 组件库、设计系统、需要高度定制化的项目

小型项目、快速原型、对构建流程有严格限制的场景、旧项目维护