SCSS不处理CSS变量降级,需PostCSS插件postcss-custom-properties配合preserve: false实现;变量须定义在:root且值为静态常量,fallback必须写为color: var(--c, #333);JS检测+no-cssvars类比@supports更可靠。

SCSS本身不处理CSS变量降级,必须靠PostCSS插件
SCSS编译器完全不理解var(--x),也不会尝试解析或替换它。你写的@include color-theme里哪怕包含color: var(--text-color),最终输出的还是原样字符串。真正起作用的是构建阶段的postcss-custom-properties,不是SCSS逻辑。
关键点:这个插件只在CSS层工作,且必须设preserve: false——否则它只会生成双声明:color: #333; color: var(--text-color);,而IE11看到第二行就跳过整条规则,取初始值(比如透明背景、黑色文字),不是“颜色没变”,是样式链断裂。
-
preserve: false才真正移除var()调用,只保留降级后的静态值 - 变量定义必须在
:root,且值为纯静态常量:--primary: #007bff;✅,--size: calc(1rem + 2px);❌ - Webpack/Vite中,确保
postcss-custom-properties在autoprefixer之前运行,否则可能被后续处理干扰
后备值必须和var()写在同一行
这是IE兼容最易踩坑的地方。很多人以为写两行就能 fallback:color: #333;换行再写color: var(--text-color);,结果IE11取的是第二行的无效值,回退到继承色或initial,页面大面积失色。
正确写法只有一种:color: var(--text-color, #333);。浏览器看到var()函数时,如果无法解析(如IE11),就自动取逗号后第一个合法值;现代浏览器则优先使用变量值。
立即学习“前端免费学习笔记(深入)”;
- 嵌套
var(--a, var(--b, #000))在IE里只认最外层#000,但无实际意义,因为IE根本不解析任何var() -
calc(100% - var(--gap))这种写法PostCSS默认不处理——整个calc()表达式会被IE parser直接跳过,必须手动拆解为calc(100% - 12px) - 媒体查询内定义的变量(如
@media (min-width: 768px) { :root { --gap: 16px; } })通常无法被PostCSS回溯解析,建议提至顶层:root
JS检测+no-cssvars类比@supports更可靠
@supports (background: var(--x))在IE11里根本不会被识别,整条规则包括里面的内容都会被忽略,不能作为降级依据。而CSS.supports('--x')在IE里会报TypeError,必须传完整声明字符串。
推荐做法是用JS检测后给<html>加no-cssvars类:
if (!CSS.supports('color', 'var(--_)')) document.documentElement.classList.add('no-cssvars');再配合CSS兜底:
.btn { background-color: var(--primary); }
.no-cssvars .btn { background-color: #007bff; }- 这个
no-cssvars类要覆盖所有关键样式,不能只写一两个选择器 - 如果同时用了
css-vars-ponyfill,就不能设preserve: false——否则ponyfill找不到原始var()无法运行时替换 - PostCSS插件对JS动态设置的变量(如
el.style.setProperty('--c', 'red'))完全无能为力,这部分逻辑需单独处理或放弃IE支持
不要混用SCSS变量和CSS变量做降级
有人试图用SCSS的$primary: #007bff;配合color: var(--primary, $primary);,这是错的。var(--primary, $primary)语法非法,SCSS不会把$primary注入到CSS变量fallback里,编译后就是字面量$primary,浏览器直接报错。
SCSS变量是编译期常量,CSS变量是运行时机制,两者生命周期完全不同。想共存只能靠两套独立流程:SCSS变量控制构建输出(如$legacy-support: true),CSS变量靠PostCSS+JS兜底。
- SCSS里可以封装
@mixin theme-button($bg: #007bff)用于生成基础样式,但它和var(--primary)无关 - 所有能被PostCSS降级的CSS变量,必须满足硬约束:定义在
:root、值为静态常量、无跨文件引用、无calc()嵌套 - 真正容易被忽略的是
calc()里嵌套var()——这类写法必须手动拆解,或改用JS注入内联样式


















