在 Vue 项目中,Sass/Scss 和 Less 均为常用的 CSS 预处理器,核心作用是通过「变量、嵌套、混合、函数」等特性简化 CSS 编写、提升可维护性,但二者在语法设计、生态支持、功能细节上存在差异,以下从 核心区别 和 Vue 项目中的具体写法 两方面详细说明:
一、Sass/Scss 与 Less 的核心区别
Sass(Syntactically Awesome Style Sheets)最初是为 Ruby 设计的预处理器,后来衍生出兼容 CSS 语法的 Scss(Sassy CSS)(也是目前主流写法);Less(Leaner Style Sheets)则是基于 JavaScript 开发,更注重轻量和易用性。二者核心区别可通过下表对比:
对比维度 | Sass/Scss | Less |
---|---|---|
语法风格 | - Scss:兼容 CSS 语法,需用 {} 包裹代码、; 结尾(如 div { color: red; } )- 原生 Sass(旧版):无 {} 和 ; ,依赖缩进(类似 Python,现已少用) |
完全兼容 CSS 语法,必须用 {} 和 ; (与 Scss 语法一致) |
变量定义 | 使用 $ 符号,如 $primary-color: #1890ff; |
使用 @ 符号,如 @primary-color: #1890ff; |
嵌套规则 | 支持普通嵌套、父选择器 & 、属性嵌套(如 font: { size: 14px; weight: bold; } ) |
支持普通嵌套、父选择器 & ,不支持属性嵌套 |
混合(Mixin) | - 定义:@mixin 名称(参数) { ... } - 调用: @include 名称(参数); 支持默认参数、可变参数 |
- 定义:.mixin 名称(参数) { ... } 或 @mixin 名称(参数) { ... } - 调用: @include 名称(参数); 或直接类名调用(如 .box { .mixin(); } )支持默认参数,可变参数支持较弱 |
继承(Extend) | 使用 @extend 选择器; ,支持继承多个选择器,且会智能合并相同样式(减少冗余) |
使用 &:extend(选择器); ,仅支持单选择器继承,合并逻辑较简单 |
函数(Function) | 内置丰富函数(如颜色处理 lighten() 、数值计算 round() ),且支持自定义函数(@function ... @return ) |
内置函数较少(仅基础数值 / 颜色计算),不支持自定义函数 |
条件判断 | 支持 @if / @else if / @else 条件语句,可结合变量动态控制样式 |
支持 @if / @else ,但条件判断能力较弱(不支持 @else if ,需嵌套实现) |
循环 | 支持 @for (固定次数循环)、@each (遍历列表 / 映射)、@while (动态次数循环) |
仅支持 @for 循环(语法与 Sass 类似),不支持 @each 和 @while |
生态与工具链 | 生态更成熟,广泛用于 Vue、React 等框架,与 dart-sass (当前主流 Sass 编译器)深度集成,支持更多高级特性 |
生态较轻量化,适合简单场景,编译器基于 JavaScript(less 包),编译速度略快于 Sass |
适用场景 | 大型项目、复杂样式逻辑(如组件库、主题系统),需要强扩展性和丰富功能 | 中小型项目、简单样式需求,追求轻量和快速上手 |
二、Vue 项目中 Sass/Scss 与 Less 的配置与写法
Vue 项目(尤其基于 Vite 构建的项目)对二者的集成流程类似,需先安装依赖,再通过 vite.config.js
配置全局变量(可选),最后在组件中使用。以下以 Vite + Vue 3 为例,分别说明具体步骤:
1. 通用前置步骤:安装依赖
无论使用 Sass/Scss 还是 Less,都需先安装「预处理器本身」和「Vite 适配插件」(Vite 内置了对二者的支持,无需额外插件,仅需安装预处理器核心包)。
安装 Sass/Scss 依赖
bash
# 安装 dart-sass(当前推荐,替代旧版 node-sass)
npm install sass -D
# 或 yarn
yarn add sass -D
安装 Less 依赖
bash
npm install less -D
# 或 yarn
yarn add less -D
2. 可选配置:全局变量(避免重复引入)
若项目中需使用全局变量(如主题色、字体大小),可在 vite.config.js
中配置「全局预处理器选项」,避免在每个组件中重复 @import
。
配置 Sass/Scss 全局变量
假设全局变量文件路径为 src/styles/variables.scss
,配置如下:
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
// 配置全局变量(注意:末尾需加 ;,否则会报错)
additionalData: `@import "@/styles/variables.scss";`
}
}
}
})
配置 Less 全局变量
假设全局变量文件路径为 src/styles/variables.less
,配置如下:
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
less: {
// 配置全局变量(同样需加 ;)
additionalData: `@import "@/styles/variables.less";`,
// 可选:启用 Less 的 JavaScript 计算(支持在 Less 中使用 JS 表达式)
javascriptEnabled: true
}
}
}
})
3. Vue 组件中的具体写法(对比示例)
以下通过「变量、嵌套、混合、继承」等核心特性,对比二者在 Vue 单文件组件(SFC)中的写法:
示例 1:Sass/Scss 写法(推荐用 Scss 语法)
vue
<template>
<div class="scss-demo">
<h2 class="title">Sass/Scss 示例</h2>
<p class="content">这是一段测试文本</p>
<button class="btn primary-btn">主要按钮</button>
</div>
</template>
<style lang="scss" scoped>
// 1. 使用全局变量(已在 vite.config.js 配置,无需 import)
// 2. 嵌套规则(含父选择器 &)
.scss-demo {
width: 800px;
margin: 0 auto;
padding: 20px;
border: 1px solid $border-color; // 全局变量 $border-color
// 嵌套子选择器
.title {
font-size: $font-size-lg; // 全局变量 $font-size-lg
color: $text-color-primary; // 全局变量 $text-color-primary
margin-bottom: 16px;
// 父选择器 &(hover 状态)
&:hover {
color: lighten($text-color-primary, 10%); // 内置函数 lighten()(颜色变浅 10%)
}
}
.content {
font-size: $font-size-base;
color: $text-color-secondary;
line-height: 1.5;
}
}
// 3. 混合(Mixin):可复用样式片段(带参数)
@mixin btn-style($bg-color, $text-color, $padding: 8px 16px) { // 默认参数 $padding
padding: $padding;
background-color: $bg-color;
color: $text-color;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: darken($bg-color, 5%); // 内置函数 darken()(颜色变深 5%)
}
}
// 4. 调用混合
.btn {
@include btn-style(#f5f5f5, #333); // 使用默认 padding
}
.primary-btn {
@include btn-style($primary-color, #fff, 10px 24px); // 自定义 padding
}
// 5. 继承(Extend):复用已有选择器样式
.success-btn {
@extend .btn; // 继承 .btn 的基础样式
background-color: $success-color; // 覆盖背景色
&:hover {
background-color: darken($success-color, 5%);
}
}
</style>
示例 2:Less 写法
vue
<template>
<div class="less-demo">
<h2 class="title">Less 示例</h2>
<p class="content">这是一段测试文本</p>
<button class="btn primary-btn">主要按钮</button>
</div>
</template>
<style lang="less" scoped>
// 1. 使用全局变量(已在 vite.config.js 配置)
// 2. 嵌套规则(含父选择器 &,但无属性嵌套)
.less-demo {
width: 800px;
margin: 0 auto;
padding: 20px;
border: 1px solid @border-color; // 全局变量 @border-color
.title {
font-size: @font-size-lg;
color: @text-color-primary;
margin-bottom: 16px;
&:hover {
color: @text-color-primary + #111; // Less 基础颜色计算(类似 JS 加法)
}
}
.content {
font-size: @font-size-base;
color: @text-color-secondary;
line-height: 1.5;
}
}
// 3. 混合(Mixin):语法与 Scss 类似,但定义可用 .mixin 或 @mixin
.mixin btn-style(@bg-color, @text-color, @padding: 8px 16px) { // 默认参数 @padding
padding: @padding;
background-color: @bg-color;
color: @text-color;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: @bg-color - #050505; // Less 基础颜色计算
}
}
// 4. 调用混合(两种方式)
.btn {
.btn-style(@gray-color, #333); // 方式 1:直接调用类名
// @include btn-style(@gray-color, #333); // 方式 2:用 @include(与 Scss 一致)
}
.primary-btn {
.btn-style(@primary-color, #fff, 10px 24px);
}
// 5. 继承(Extend):必须用 &:extend()
.success-btn {
&:extend(.btn); // 继承 .btn 的基础样式
background-color: @success-color;
}
</style>
三、总结与选择建议
- 语法兼容性:Scss 和 Less 均兼容 CSS,新手可快速上手;若习惯缩进语法,可尝试原生 Sass(但不推荐,生态已边缘化)。
- 功能丰富度:Sass > Less,尤其在「自定义函数、循环、条件判断」上,Sass 更适合复杂项目(如组件库开发)。
- 生态与性能:Sass 生态更成熟(如 Vue 官方组件库
Element Plus
用 Scss),dart-sass
编译性能稳定;Less 更轻量,适合简单场景。
选择建议:
- 大型项目、需复杂样式逻辑 → 优先 Sass/Scss;
- 中小型项目、追求轻量快速 → 可选 Less;
- 团队已有 CSS 基础 → 优先 Scss(降低学习成本,兼容 CSS 语法)。