SCSS单位转换异常的根本原因是单位校验缺失、基准值错位或混淆编译期与运行时逻辑。需用unitless()补单位、统一$rem-base为无单位数、@use "sass:math"并用math.div()、calc中用#{}插值且确保单位和空格正确。

SCSS单位转换函数结果异常,根本原因不是“写错了公式”,而是单位校验缺失、基准值错位、或把编译期计算当运行时逻辑用——三者任一出问题,输出的 CSS 就会是无效值或尺寸错乱。
px-to-rem 函数传入 14 就报错 Incompatible units
这是最典型的单位类型未校验导致的崩溃。SCSS 不会自动把 14 当作 14px;它就是个无单位数字,而你的函数体里直接写了 $px / 16px,等于拿数字除以带单位值,触发单位不兼容错误。
- 必须在函数开头加判断:
@if unit($px) != "px" { @warn "expected px, got #{unit($px)}"; @return $px; } - 对无单位输入(如
14),可选择主动补单位:@if unitless($px) { $px: $px * 1px; },但得明确这是业务约定,不是通用解法 - 别用
strip-unit():SCSS 3.5+ 已弃用,且它不处理单位缺失场景;unitless()+ 手动补单位更可控
SCSS 算出来是 2rem,但页面上元素小得看不见
这说明 SCSS 的换算基准和 JS 运行时设置的 html 字体大小不一致。SCSS 编译完就结束了,它不知道 JS 后续把 document.documentElement.style.fontSize 设成了多少。
- 基准值必须统一为无单位数字,例如定义
$rem-base: 100(不是100px) - JS 里对应写:
document.documentElement.style.fontSize = clientWidth / 7.5 + "px"→ 实际 1rem = 100px - SCSS 函数内一律用
math.div($px, $rem-base) * 1rem,杜绝硬编码37.5或75这类设计稿分母 - 高 DPR 屏幕下,JS 必须乘
window.devicePixelRatio,否则逻辑像素没变,物理渲染却缩了
用了 math.div() 还是报 Function "math.div" not found
这不是函数写错了,是 Dart Sass 版本升级后模块加载规则变了。Dart Sass ≥4.0 要求显式导入数学模块,且不能省略命名空间。
- 必须在使用前加:
@use "sass:math"(注意不是@import) - 调用时写全:
math.div($a, $b),不能只写div($a, $b) - 如果项目混用旧版 LibSass 或 Dart Sass 3.x,
math.div根本不存在,得降级用/并严格限定上下文(仅 font/grid 等支持斜杠的属性中) -
/在普通属性里(如width: 100px / 2)会直接报Invalid CSS after "100px",这不是 bug,是新版 Sass 的语法限制
calc(100% - $gap) 编译后变成 calc(80%),完全不是想要的运行时计算
SCSS 把变量当自己人提前算了,浏览器根本没机会执行 calc。所有想留给浏览器运行时处理的表达式,必须用 #{} 插值包裹,且确保空格、单位、父容器高度都到位。
- 正确写法:
calc(100% - #{$gap}),其中$gap必须是带单位的值(如20px) - 避免在插值外做运算:
calc(100vh - $header - $footer)❌,应先合并:$offset: math.div($header + $footer, 1); calc(100vh - #{$offset})✅ - 空格不能少:
calc(100%-20px)浏览器直接忽略整条声明,必须是calc(100% - 20px) - 父容器高度为
auto时,height: calc(100% - 60px)中的100%基准是 0,结果恒为负,浏览器丢弃 —— 这跟 SCSS 无关,是 CSS 渲染机制
真正难的不是写出一个能跑的函数,而是让这个函数在任意输入、任意基准、任意调用位置下,返回的都是合法 CSS 值。单位、类型、基准对齐,三者缺一不可;任何一处松动,都会在某个深夜的 QA 环节突然崩出来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











