Less 中没有 em() 和 rem() 函数,需用 unit() 剥离单位后手动计算倍数,如 unit(24px,'')/unit(16px,'')*1em 得 1.5em;可封装 .to-em(@target, @base) 宏复用,但结果为静态值,无法响应运行时根字号变化。

Less 中的 em() 和 rem() 函数不能直接计算字体倍数
Less 官方内置函数里根本没有 em() 或 rem() —— 这是常见误解。你写 em(16px) 会报错:undefined function em。Less 只提供数学运算和单位转换基础能力,倍数关系得靠手动算或封装逻辑。
真正能用的只有:unit()(剥离单位)、percentage()(转百分比)、round()(四舍五入),以及加减乘除运算符。比如把 16px 换算成相对于 14px 的倍数,得自己写:16px / 14px,结果是 1.1428571429(无单位数值)。
- 单位相除会自动消去,
16px / 14px→ 数值1.142857;16px / 14em→ 报错,单位不兼容 - 想保留小数位?用
round(16px / 14px, 2)得到1.14 - 别对带单位的值直接调用
percentage(),percentage(1.14)是114%,不是你想要的倍数
用 unit() + 除法安全提取基准倍数
当你要基于某个根字号(比如 @base-font-size: 16px)动态生成 h1、h2 的 em 值时,关键不是“转换”,而是“归一化”。先用 unit() 剥离单位再除,比硬写 1.5em 更可控。
@base-font-size: 16px;
@h1-size: 24px;
<p>// 安全得到倍数:1.5
h1 {
font-size: unit(@h1-size, '') / unit(@base-font-size, '') * 1em;
}
-
unit(@h1-size, '')返回纯数字24,unit(@base-font-size, '')返回16 - 乘以
1em是为了带上单位,否则 Less 编译后是无单位数值,CSS 不认 - 如果
@h1-size是1.5em,unit()会失败(Less 无法从em提取数值),所以输入必须统一用px或纯数字
封装一个 to-em() 混合宏避免重复计算
每次手写 unit() / unit() * 1em 易错且难读,不如封装成可复用的混合宏。它不依赖全局变量,传入目标尺寸和基准尺寸即可:
立即学习“前端免费学习笔记(深入)”;
.to-em(@target, @base: 16px) {
@ratio: unit(@target, '') / unit(@base, '');
font-size: @ratio * 1em;
}
<p>// 使用
h2 { .to-em(20px, 16px); } // → font-size: 1.25em
small { .to-em(12px, 16px); } // → font-size: 0.75em
- 注意
@base默认值写成16px而不是16,否则传入14px时类型不匹配会编译失败 - 如果基准是
html { font-size: 10px; },调用时必须显式传.to-em(16px, 10px),不能只改默认值——因为 Less 没有运行时获取 CSS 计算值的能力 - 这个宏只处理
font-size,其他属性如margin需要另写类似逻辑,不能复用
警惕 px-to-em 转换在响应式场景下的失效点
用 Less 算出来的 em 值是静态的,一旦根元素字体被媒体查询修改(比如 @media (max-width: 768px) { html { font-size: 14px; } }),你预设的 1.5em 就不再等于原意的 24px。
- Less 编译阶段无法感知媒体查询,所有
em值都是基于你写死的@base-font-size算出来的 - 真要响应式适配,要么改用
clamp()+rem(现代 CSS),要么用 JavaScript 动态重算 —— Less 本身做不到 - 如果你项目已用
postcss-plugin自动转px到rem,就别在 Less 里重复造轮子,反而容易冲突
Less 的数学能力够用,但它的“编译时”本质决定了它只能做确定性换算。倍数关系是否真能落地,取决于你是否清楚 CSS 运行时的实际根字号是多少 —— 这一点,Less 永远不会告诉你。


















