该用 rem 而非 em 时:需全局缩放、响应式字体或避免嵌套计算爆炸;rem 基于 html 根元素 font-size,改一处全站响应,而 em 易因继承嵌套失控,适合局部微调。

什么时候该用 rem,而不是 em
当你要做全局缩放、响应式字体或避免嵌套计算爆炸时,直接选 rem。它只认 html 根元素的 font-size,改一处,全站字体按比例动。比如适配移动端:在媒体查询里调一次 html { font-size: 10px; },所有 1.4rem 自动变成 14px。
em 只适合局部微调——比如按钮内图标大小跟着按钮文字走,或某段注释文字设为父容器的 0.8em。但它一旦嵌套三层,就容易失控:
.card { font-size: 1.2em; } /* 假设 body 是 16px → 这里是 19.2px */
.card__title { font-size: 1.5em; } /* → 19.2 × 1.5 ≈ 28.8px */
.card__title small { font-size: 0.7em; } /* → 28.8 × 0.7 ≈ 20.16px(不是你预期的 16×0.7=11.2)*/
em 的继承陷阱和常见报错现象
浏览器不会报错,但你会看到字体“莫名其妙变大”或“越缩越小”,尤其在组件库嵌套、CSS-in-JS 动态注入、或用了 font-size 重置但没清空继承链时。
- 父元素没显式设
font-size,em就回退到浏览器默认(通常是16px),但不同 UA 可能不同 - 用
em写padding或margin,结果发现按钮在标题下变高了——因为标题改了font-size,连带 padding 也放大 - Vue/React 组件中父子都用
em,props 传字体大小后,子组件再套一层em,数值翻倍
怎么安全地用 rem?别只写 html { font-size: 16px; }
硬写死 16px 就失去了 rem 的意义。真正实用的做法是用视口宽度动态算根字号:
立即学习“前端免费学习笔记(深入)”;
html {
font-size: clamp(12px, 2.5vw, 16px); /* 小屏最小12px,大屏不超16px,中间线性过渡 */
}
/* 或更精准的移动端方案 */
@media (max-width: 750px) {
html { font-size: 10px; } /* 此时 1rem = 10px,14px → 1.4rem,好算 */
}注意:rem 对 border、shadow 等非字体属性也生效,但一般不推荐——边框粗细不该随根字号缩放,这类地方还是用 px 更可控。
兼容性和 fallback 怎么写才不翻车
IE8 不支持 rem,但你现在基本不用管它;真正要防的是 JS 动态修改根字号失败、或用户禁用了字号缩放导致 rem 失效。
- 所有关键文本样式,建议双写:
font-size: 14px; font-size: 0.875rem;——老浏览器吃第一行,新浏览器覆盖第二行 - 不要依赖 JS 设置
document.documentElement.style.fontSize后立刻读取计算值,DOM 渲染有延迟,可用getComputedStyle确认 - 用
rem做间距时,如果设计稿以px为单位,别心算:12px / 16px = 0.75rem;但若根字号是10px,就得除以 10 —— 混用会错乱
最常被忽略的一点:字体可访问性。用户在系统设置里放大文字(比如 Windows 的“放大文本”或 macOS 的“更大字体”),rem 会响应,px 不会,而 em 可能因继承链断裂反而失效。这点在政企、教育类项目里不能跳过。










