一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何在SCSS中安全计算CSS的rem单位

时间:2026-08-07 14:53:49 编辑:袖梨 来源:一聚教程网

SCSS中rem函数必须进行类型与单位校验,否则传入无单位数字或非px值将报错;基准值须为无单位数字(如$rem-base: 100),JS动态设置html font-size严格对齐该基准,且函数需全局注入。

SCSS里rem函数必须带单位检查

直接写 @function rem($px) { @return $px / 100 * 1rem; } 看似简洁,但一旦传入 14(无单位)或 1.5rem,编译就报错 Incompatible units。SCSS不自动补单位,也不做隐式转换。

正确做法是加类型和单位校验:

  1. type-of($px) == "number" 排除非数字输入
  2. unit($px) == "px" 确保只处理带 px 单位的值
  3. 对无单位数字(如 14)主动警告,不静默转成 14px
  4. 返回值必须是带 1rem 的合法CSS值,不能是纯数字

示例修正式版:

@function rem($px) {@if type-of($px) != "number" {@warn "rem() expects a number, got #{type-of($px)}";@return $px;}@if unit($px) != "px" {@warn "rem() expects px unit, got #{unit($px)}";@return $px;}@return ($px / 100) * 1rem;}

基准值 $rem-base 必须全局统一且无单位

很多人把 $rem-base: 37.5px 写进变量,结果所有 rem(750) 都算成 20rem —— 因为 750px / 37.5px = 20,但 JS 实际设置的是 html { font-size: 37.5px; },1rem 就真是 37.5px,这没问题;可一旦换设计稿宽为 640px,JS 改设 font-size: 64px,而 SCSS 还按 37.5 算,尺寸就全乱了。

真正安全的做法是:

  1. $rem-base: 100(纯数字,无单位)
  2. JS 设置 document.documentElement.style.fontSize = clientWidth / 7.5 + "px" → 保证 1rem = 100px
  3. SCSS 函数内一律用 $px / $rem-base,不掺杂任何像素字面量
  4. 所有媒体查询、响应式分支都只动 JS,不动 SCSS 基准

别在SCSS里尝试“运行时适配”

看到 “iPhone X 屏幕窄,字号该小一点”,就想着在 @media (max-width: 375px) 里重定义 $rem-base: 90 —— 这完全无效。SCSS 变量在编译期就固化了,媒体查询块里的变量重声明,只作用于该块内新生成的 CSS,不会回溯修改之前已计算好的 rem() 值。

真正起效的路径只有一条:

  1. JS 监听 resizeDOMContentLoaded,实时重设 html.style.fontSize
  2. document.documentElement.clientWidth(非 window.innerWidth),排除滚动条干扰
  3. 加防抖(如 100ms 节流),避免 resize 频繁触发重排
  4. 对极端小屏加最小字号兜底:fontSize = Math.max(12, clientWidth / 7.5)

Vue/Vite项目中函数必须全局注入

.vue 文件的 <style lang="scss"> 里写 font-size: rem(20); 报错 Undefined function "rem",不是函数写得不对,而是根本没被加载。

必须显式配置预处理器注入:

  1. Vue CLI:在 vue.config.jscss.loaderOptions.sass.prependData 中导入
  2. Vite:在 vite.config.tscss.preprocessorOptions.scss.additionalData 中导入
  3. 路径要写对,比如 @import "@/styles/functions.scss";,且该文件不能含任何 html { ... } 规则
  4. 别用 @use@forward —— 它们不支持跨文件全局函数调用

最易忽略的一点:函数文件里不能有 @import 循环引用,否则整个 SCSS 编译链会静默失败,错误提示极不明确。

热门栏目