sass 中无法直接使用 var(--size),因其运行在构建阶段,而 var() 是浏览器运行时解析的 css 函数;必须用 calc() 在 css 中完成动态计算,或通过插值将 sass 变量注入 css 自定义属性。

为什么 var(--size) 在 Sass @function 里直接报错
Sass 编译器根本“看不见” var(--size) ——它不是 CSS 值,而是浏览器渲染引擎在 DOM 挂载后才解析的运行时表达式。Sass 运行在构建阶段(Webpack 启动、sass-loader 执行时),此时 HTML 还没加载,:root 根本不存在,document.documentElement 是 undefined。
所以像这样写注定失败:
@function pxToRem($px) {
$base: var(--base-font-size); // ❌ Sass 报错:Unrecognized input
@return #{$px / $base} + rem;
}
错误不是语法不对,而是 Sass 解析器压根不识别 var() 这个 token,更不会把它当数值参与除法。
$base: 16px 和 --base-font-size: 16px 的本质区别
两者名字像,但生命周期和作用域完全不同:
-
$base: 16px是 Sass 编译期常量,所有@include、@mixin、@function都能直接用它做乘除、条件判断、循环生成类名 -
--base-font-size: 16px是 CSS 运行时变量,只在浏览器样式计算阶段生效;它能被var()引用,也能进calc(),但仅限于 CSS 属性值上下文(比如width: calc(100% / var(--cols))) - 你不能在 Sass 里对
--base-font-size做@if $base > 20px,也不能把它传给lighten($color, 10%)
想让 rem 随 JS 动态缩放?别在 Sass 里算除法
常见需求是:JS 根据屏幕宽度设置 :root 的 --base-font-size,然后所有 rem 自动响应。这时候必须放弃“Sass 算完再输出 rem”的思路:
- ❌ 错误做法:试图在 Sass 中读取并除——编译不过,或输出非法 CSS(如
16/var(--base-font-size)rem) - ✅ 正确路径:用
calc()把计算逻辑留在 CSS 运行时@mixin rem-width($px) { width: calc(#{$px} / var(--base-font-size) * 1rem); } - 编译结果是合法 CSS:
width: calc(320 / var(--base-font-size) * 1rem);,浏览器每次重绘都重新求值 - 注意:
calc()内部单位要一致——var(--base-font-size)必须是纯数字(如16)或带单位值(如16px),否则除法会失效
在 :root 里用 Sass 变量初始化 CSS 变量?必须插值
Sass 变量可以“注入”到 CSS 变量定义中,但必须显式用 #{$var} 插值,否则会被当字面量处理:
$base-font-size: 16px;
:root {
--font-size-m: #{$base-font-size}; // ✅ 编译为 --font-size-m: 16px;
--font-size-l: #{$base-font-size * 2}; // ✅ 编译为 --font-size-l: 32px;
--font-size-s: calc(#{$base-font-size} / 2); // ✅ 编译为 --font-size-s: calc(16px / 2);
--broken: $base-font-size; // ❌ 编译为 --broken: $base-font-size;(无效)
}
这里的关键是:Sass 只负责字符串替换,不负责 CSS 语义校验。插值后的结果是否合法(比如单位能否参与 calc),得由浏览器 runtime 判断。
复杂点在于混合场景:比如你既想用 Sass 做主题色预计算(darken($primary, 10%)),又想把结果暴露为 CSS 变量供 JS 调用。这时必须分两层——Sass 层生成确定值,再通过插值写入 :root;任何试图跨阶段桥接(编译期 ↔ 运行时)的操作,都会掉进执行时机的坑里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











