用 unit() 函数最可靠判断sass值是否带单位,它返回单位字符串如"px"或空字符串"",而type-of()无法区分带单位与无单位数字,且必须配合unitless()安全提取数值。

怎么判断一个Sass值是否带单位
直接用 unit() 函数最可靠——它返回字符串,比如 unit(10px) 得 "px",unit(2em) 得 "em",而无单位数值(如 42、-3.14)返回空字符串 ""。别用 type-of(),它对所有数字都返回 "number",没法区分 10 和 10rem。
常见错误是写 @if $val > 0 就默认它是纯数字,结果传进 20vh 会编译报错:"Incompatible units: 'vh' and ''." —— 这说明你没提前检查单位。
- 用
@if unit($val) == ""判断是否为无单位数 - 用
@if unit($val) == "px"做精确单位匹配(注意大小写,"PX"不等于"px") - 避免在未校验前把带单位值和无单位值直接相加或比较
如何安全地把带单位的值转成像素
Sass 本身不提供运行时单位换算(比如 rem → px),所谓“转换”其实是靠你定义基准并手动计算。核心思路:提取数值部分 + 乘以基准系数。关键函数是 unitless() 和 unit() 配合使用。
例如想把 1.5rem 转成像素(假设根字号为 16px):
立即学习“前端免费学习笔记(深入)”;
$val: 1.5rem;
$base: 16px;
@if unit($val) == "rem" {
$px-val: unitless($val) * $base; // 得到 24px
}容易踩的坑:
-
unitless(10px)返回10(数值类型),但unitless(10)也返回10—— 所以必须先用unit()确认单位再调用unitless() - 别对
vh/vw做静态转像素,它们是视口相对单位,无法在编译期转成固定px - 混用单位做算术(如
1rem + 10px)会触发 Sass 编译错误,不是运行时问题
为什么不能直接用 assert-unit() 做类型守卫
Sass 官方没有 assert-unit() 这个函数——这是很多人搜错的关键点。实际能用的是社区封装的逻辑,或者自己写简易断言。真正起作用的是组合判断:unit($val) == "" 或 unit($val) == "px"。
典型误用场景:在 mixin 中接收 $size 参数,期望它总是 px,但用户传了 2em,又没校验,结果生成了 font-size: 2empx; 这种非法 CSS。
- 推荐写法:
@if unit($size) != "px" and unit($size) != "",然后@error "Expected px or unitless value, got #{$size}" - 不要依赖
comparable()来“兼容单位”,它只判断能否运算(如1px == 1px是 true,但1px == 1em是 false),不解决语义安全问题 - 如果允许多种单位(如支持
px、rem、em),必须显式分支处理,不能靠隐式转换
Unit 函数在响应式断点中的实际约束力
unit() 在断点变量里特别有用,但也很容易被忽略其局限性。比如定义 $md: 768px,你希望 min-width: $md 永远输出合法媒体查询,那就得确保 $md 真的是带 px 的值。
问题常出在动态构造断点时:从 map 取值、拼接字符串、或通过函数生成——这些过程可能意外剥离单位。
- 读取 map 值后立刻用
@if unit(map-get($breakpoints, md)) != "px"校验 - 避免用字符串拼接构造尺寸:
"#{$n}px"得到的是字符串,不是 Sass 数字,后续无法参与计算 - 用
feature-query或现代 CSS @container 时,单位检查逻辑不变,但注意 Sass 无法验证容器查询中的inline-size单位是否合法
单位安全不是一劳永逸的事——只要值经过参数传递、map 查找、循环迭代或函数返回,就得重检 unit()。这看起来啰嗦,但比上线后发现按钮宽度突然变成 0px(因为某个 0 被当成了 0em)要好得多。










