rem适合全局缩放但需主动控制根字号,必须显式设置html{font-size:16px}并动态干预(如clamp或JS),em适合组件内局部缩放但需注意参照规则差异,混用单位易导致参照系混乱。

rem适合全局缩放,但必须主动控制根字号
光写 html { font-size: 16px } 不叫响应式,那是固定尺寸。rem 本身不自动响应,它只忠实地乘以当前 html 的最终计算值。如果你没动过根字号,浏览器默认是 16px,但 iOS Safari 可能在双击缩放后悄悄改掉它——所以第一件事是显式锁死:html { font-size: 16px; },别留空、别靠继承。
真正让 rem 动起来的,是后续对这个值的动态干预:
- 推荐用
html { font-size: clamp(14px, 2.5vw, 18px); }:小屏保可读、大屏不溢出、中间平滑过渡,Safari 13.1+ 和 Chrome 88+ 支持良好 - 若需兼容 Safari 12 或更低版本,JS 方案仍是底线:
document.documentElement.style.fontSize必须在DOMContentLoaded后立即执行,否则首屏渲染取不到视口宽 - 别用
font-size: 62.5%这类“方便心算”的写法——它依赖用户系统默认字号,且和 macOS + Safari 的字体缩放功能冲突
em适合组件内局部缩放,但参照规则容易混淆
em 不是统一参照父级;它的基准会随属性位置切换:font-size 看父元素,padding 和 margin 却看**当前元素自身的 font-size**。这个差异是绝大多数 em 调试失败的根源。
例如:.btn { font-size: 14px; padding: 0.75em; } 中的 0.75em 是 10.5px(基于按钮自身字号);但如果漏写了 font-size,它就继承自 body 的 16px,后续主题换字体时所有按钮内边距全乱。
立即学习“前端免费学习笔记(深入)”;
安全使用 em 的前提是:组件自身显式声明了 font-size,且嵌套层级 ≤ 2。
- 适合场景:按钮内边距随文字等比撑开、icon-font 图标尺寸贴合文本基线、
border-width需随文字粗细微调(如border: 0.0625em solid) - 危险信号:卡片里
padding: 1em,但标题用1.5rem、正文用px——混用等于放弃间距逻辑一致性 - 绝对陷阱:
line-height: 1.5em(会二次乘以自身字号),正确写法是line-height: 1.5(无单位)
混用单位时最隐蔽的坑不是数值算错,而是参照物打架
单位选错不会报错,但会让样式在缩放、嵌套或主题切换时突然失衡。比如用 rem 写字体大小,却用 px 写行高,一旦根字号调整,行高就不会同比例变化,行距立刻崩塌。
更常见的是“伪响应”:全局用 rem,但某个弹窗组件 JS 动态设置了父容器的 font-size,结果里面所有 em 值被带偏,按钮文字变小、间距变大,调试时得逐层回溯。
- 同一套设计系统里,基础间距变量(如
$space-md)必须统一用rem或统一用em,不能并存 -
border-radius、box-shadow、border这些要像素级精准的属性,一律用px,避免被缩放干扰细节 - CSS 自定义属性(如
var(--base-font))不能参与rem计算——rem只认html最终渲染值,不是变量名
真正难的不是选单位,而是守住参照系边界
一旦你决定用 rem 做全局尺度,就别让任何父容器偷偷改 font-size;一旦用 em 做局部缩放,就别指望它能响应屏幕宽度。单位本身没对错,错的是参照逻辑被悄悄污染。
最容易被忽略的一点:很多团队用 rem 却忘了重置 html 的初始 font-size,导致 1rem 在不同设备上漂移——这不是单位问题,是契约没签清楚。


















