Less中直接用rem不生效,因其是编译时预处理器,无法感知运行时根字体大小,只能通过px2rem函数或mixin在开发阶段静态将px按约定比例(如750px设计稿下1rem=75px)转为rem。

为什么直接用 rem 在 Less 里不生效
Less 是编译时预处理器,它无法感知运行时的根字体大小(document.documentElement.style.fontSize),更没法动态把设计稿里的 px 值按当前 rem 基准换算。所谓“自动转换”,本质是开发阶段的静态替换——靠函数或 mixin 把写死的像素值,按约定比例转成 rem 单位。
用 px2rem() 函数实现编译期转换
Less 不内置 px2rem(),需手动定义。常见做法是假设设计稿宽度为 750px,1rem = 75px(即 750 / 10),这样 100px → 1.3333rem。函数要支持单值、多值、带单位校验:
.px2rem(@px) when (isnumber(@px)) {
@rem: unit(@px / 75, rem);
}
.px2rem(@px) when not (isnumber(@px)) {
@rem: @px;
}
// 调用示例
.font-size { font-size: .px2rem(32); } // → font-size: 0.42666667rem;
- 必须显式传入纯数字(如
32),不能传32px,否则isnumber()判定失败 - 除数
75是硬编码基准,项目切换适配方案(如 375 设计稿用 37.5)时需全局替换 - 返回值带
rem单位,但 Less 编译后是静态值,不会随 JS 动态改根字号而变化
用 px2rem-mixin 批量处理属性
比函数更实用的是封装 mixin,覆盖常用属性,避免重复写转换逻辑:
.px2rem-mixin(@prop, @value) when (isnumber(@value)) {
@{prop}: unit(@value / 75, rem);
}
// 使用
.btn {
.px2rem-mixin(margin, 24);
.px2rem-mixin(padding, 16);
.px2rem-mixin(border-width, 1);
}
- 支持传入任意属性名和数值,比函数更灵活
- 不处理非数字值(如
auto、inherit),原样透传,避免编译报错 - 若属性需多个值(如
margin: 10px 20px),得拆成多个调用,Less 不支持对列表逐项映射
注意 JS 动态设置根字体与 Less 转换的分工边界
Less 的 px2rem 只负责“写的时候换单位”,而真实页面缩放依赖 JS 运行时设置 html 标签的 font-size。两者必须匹配:
立即学习“前端免费学习笔记(深入)”;
- JS 设置根字号的逻辑(如
document.documentElement.style.fontSize = docWidth / 7.5 + 'px')必须与 Less 里除数一致(这里是/ 75,因750 / 7.5 = 100,即 1rem = 100px → 实际应为/ 75对应 1rem = 75px) - 设计师给的标注是 750px 宽,你用了 375px 适配方案,Less 里却还除以 75,结果会放大 2 倍
- 媒体查询中的
max-width: 750px这类断点值,不应进px2rem转换——它基于视口物理宽度,不是字体相关尺寸
最易被忽略的是:所有转换都建立在「设计稿像素值 ÷ 基准换算系数」这一静态关系上,一旦系数在 JS 和 Less 里不统一,样式就错位,且这种错误不会报错,只在真机上表现为元素忽大忽小。


















