scss 的 @if 仅在编译时生效,依赖构建工具注入变量(如 vite/webpack 预设 $env),未注入则报错;字符串比较需加引号,多条件须加括号,真假值判断易出错;运行时环境切换必须靠 js 或构建时多输出。

为什么 @if $env == "production" 看似有效,实则靠外部注入
SCSS 的 @if 指令根本不会读取运行时环境 —— 它只在编译那一刻看一眼你塞进去的变量值。你写的 @if $env == "production" 能生效,前提是构建工具(比如 Vite 或 Webpack)提前把 $env 这个 Sass 变量设成了字符串 "production"。
常见注入方式:
- Vite:在
vite.config.ts里配css.preprocessorOptions.sass.additionalData,拼接$env: "${process.env.MODE}"; - Webpack:用
DefinePlugin把process.env.NODE_ENV映射为 Sass 变量 - Dart Sass CLI:
sass --define=env=staging main.scss:dist/main.css
没做这些?$env 就是未定义变量,编译直接报错:Undefined variable "$env"。
@if 字符串和布尔值判断最容易翻车的写法
即使变量已注入,语法或类型不对也会让分支失效:
-
@if $env == "production"✅(字符串必须加双引号) -
@if $env == production❌(会被解析成变量$production,大概率未定义) -
@if $debug✅ 当$debug: true;但$debug: false、$debug: null、$debug: ""都算“假”,而$debug: 0或$debug: ()居然算“真” -
@if ($env == "prod") and ($theme == "dark")✅(多条件必须加括号) -
@if $env == "prod" and $theme == "dark"❌(Sass 解析器会按优先级乱断,结果不可控)
调试建议:在 @if 前加一行 @debug $env;,确认值和类型是否符合预期。
真正能区分“当前环境”的只有两种方案
别指望 @if 自动感知用户点击、prefers-color-scheme 或 localStorage —— 它早在页面加载前就执行完了,输出文件里连 @if 的影子都没有,只剩它选中的那部分 CSS。
- 构建时差异化输出:跑两次编译命令,分别生成
light.css和dark.css,由 HTML 或 JS 加载对应文件 - 运行时切换靠 JS + class:Sass 里预编译好
.theme-dark { color: #fff; }和.theme-light { color: #333; },JS 控制document.documentElement.className
混用时最常被忽略的是变量作用域:用 @use 引入模块后,$env 必须在该文件中声明,或通过命名空间访问(如 config.$env),否则 @if 根本看不见它。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











