Less编译时会错误解析calc()内的表达式,导致单位运算异常;推荐用~"..."转义或e()函数绕过编译,strictMath:true虽可全局解决但迁移成本高。

Less编译时把calc()当普通表达式计算了
Less默认会解析所有含 -、+、/、* 的表达式,哪怕它写在 calc() 里。比如 calc(100% - 40px) 会被Less当成“100% 减去 40px”,而Less的减法不支持跨单位运算,于是它强行把 40px 转成百分比(按当前上下文换算),结果变成 calc(60%) 或更离谱的 calc(-150%)——浏览器根本收不到原意。
用 ~ 转义是最直接的修复方式
加 ~ 告诉Less:“这段别动,原样吐出去”。它不是字符串拼接,而是语法级转义,适用于所有含单位混合运算的场景。
width: calc(~"100% - 16px");height: calc(~"100vh - 80px");- 变量也能嵌入:
@gap: 24px; margin: calc(~"100% - @{gap}");
注意:引号必须是双引号或单引号,且 ~ 紧贴引号前,不能有空格;括号内外的空格仍需保留(calc(100% - 40px) 中的空格是CSS必需的)。
e() 函数也能绕过编译,但输出不带引号
e() 是Less内置函数,作用是“原样返回字符串,去掉引号”。它和 ~"" 效果类似,但写法稍不同:
立即学习“前端免费学习笔记(深入)”;
-
width: e("calc(100% - 16px)");→ 输出width: calc(100% - 16px); -
width: calc(~"100% - 16px");→ 输出完全一样
区别在于:e() 必须传字符串字面量,不能拼接变量(e("calc(100% - @{gap})") 会报错);而 ~"" 支持插值,更灵活。
strictMath: true 可全局禁用自动运算,但代价不小
在Less配置中启用 strictMath: true(如webpack-less-loader的math: "always"对应strictMath: false,要设为true),会让Less只计算明确用括号包住的表达式,比如 (100% - 40px) 才算,而裸写的 100% - 40px 直接原样保留。
- 好处:从此不用到处加
~,calc(100% - 40px)也能正常输出 - 坏处:所有已有Less数学运算(比如
@size: 10px * 2;)都得改成@size: (10px * 2);,老项目迁移成本高 - 不推荐仅为此问题开启——它改的是整个项目的运算规则,不是局部修复
真正容易被忽略的是:很多构建工具(如Vue CLI 4+、Vite插件)默认已启用 strictMath 或等效行为,所以你在本地less文件里写 calc(100% - 40px) 没问题,但一放到旧版Webpack + less-loader 3.x环境就崩——得看实际构建链路,不能只信文档。


















