Less中如何强制转换CSS单位适配移动端方案?
Less单位转换需手动完成:用unit()剥离单位,通过变量控制基准值,再拼接目标单位。px2rem函数须区分输入类型(纯数字、带px单位等),基准值@base-font-size需全局定义且不可在媒体查询中重定义。所有运算发生在编译期,适配需提前编译多套CSS文件。
Less单位转换的正确姿势:别指望它能自动帮你搞定rem
先说一个核心判断:Less本身并不支持运行时单位转换——它没有类似JavaScript那样的动态计算能力。所谓“强制转换”,拆开来看其实就是三步:用unit()剥离单位、通过变量控制基准值、再手动拼接目标单位。这三步缺一不可,少一个都会出问题。
举个最简单的例子:32px / 16得到的是2px,不是2rem。如果你直接把这个结果用到font-size上,浏览器要么报错,要么直接忽略。这不是Less的bug,是它的设计如此——除法默认保留左侧的单位,它不会自作主张把px变成rem。

为什么32px / 16px不能直接当rem用
原因在于Less除法的单位处理规则。当左侧是32px、右侧是16px时,结果是无单位的纯数字2。但写成32px / 16,结果却变成2px——它不会自动变成2rem。更糟糕的是,如果你写成font-size: 32px / 16px * 1rem,结果会变成2px * 1rem → 2pxrem,浏览器直接认不出来。
那正确的做法是什么?经验表明,分三步走最稳妥:
- 先用
unit(32px / 16, '')剥离单位,得到纯数字2; - 再手动拼接目标单位
2 + rem; - 或者用
unit(32px, 'px') / 16更安全,先明确提取数值再做除法。
永远别依赖隐式单位合并。Less不保证2 * 1rem会合并成2rem——某些版本甚至会输出2remrem这种奇怪的玩意儿。
.px2rem()函数必须区分输入类型
设计师给标注时没那么规矩——可能是24、24px,甚至2.4em。如果你的函数不区分输入类型,比如直接用unit(24, 'px')处理纯数字24,得到的是24px,不是想要的24。
正确的做法是添加类型判断:
- 用
isnumber(@val)判断是否为纯数字(如24); - 用
isdimension(@val)+unit(@val) = px判断是否为24px; - 遇到
2.4em这类非px单位,建议直接透传,不强行转rem; - 如果漏掉类型判断,把带px的值传进
unit(24px, ''),会报Operation on an invalid type的错误。
基准值@base-font-size必须全局定义且可覆盖
这个变量不是用来设置HTML的font-size的——它只是Less编译时做换算的标尺。它必须出现在所有调用.px2rem()的文件之前,而且不能在@media块里重定义。为什么?因为Less编译期不执行媒体查询,你写了也没用。
几个实践要点:
- 推荐在
variables.less顶部写@base-font-size: 37.5px;(对应750px设计稿÷10); - 构建时可以用Webpack的
DefinePlugin注入不同值,生成H5和小程序两套CSS; - 千万别写成
@base-font-size: 16px;然后指望JS动态改——JS改的是DOM,Less已经编译完了,两者是脱钩的; - 如果项目已经用了
postcss-pxtorem,就别在Less层再写.px2rem()了,否则px会被转两次,结果完全不对。
最后一点容易被忽略,但这才是核心逻辑:Less里所有单位运算都发生在编译期,和屏幕宽度、DPR、横竖屏毫无关系。所谓“适配”,本质上是你把多套预设值(比如@base-font-size: 37.5px和@base-font-size: 100px)提前编译成不同的CSS文件,再由JS或构建流程决定加载哪一套。指望Less自己响应viewport变化,就像让Excel表格自动调用摄像头——它没这个能力。
