结论:rem 始终相对于 html 的 font-size,em 在 font-size 中参照父元素计算后字号;padding/margin 中 em 参照自身 font-size,rem 仍参照 html;需据响应需求选单位。

直接说结论:用 rem 设置字体大小,值始终相对于 html 元素的 font-size;用 em 设置,值在 font-size 属性里看的是父元素的 font-size,不是当前元素自己的——这点最容易被误解。
font-size 里写 em,到底参照谁?
很多人以为 em 在 font-size 中总是“看自己”,其实不是。它明确看**父元素**的计算后字号:
- 如果
.card { font-size: 1.2em; },而它的父容器是body { font-size: 16px; },那.card的字号就是19.2px - 如果
.card内嵌套一个.btn { font-size: 0.8em; },那按钮字号是19.2px × 0.8 = 15.36px,不是基于根字号 -
html { font-size: 1.2em; }是危险写法——它会递归引用自身初始值(约 16px),但行为不可控,应避免
font-size 里写 rem,为什么更稳?
rem 在任何位置都只读一次 html 的 font-size,不继承、不叠加、不套娃:
-
h1 { font-size: 2rem; }和span { font-size: 2rem; }只要 html 没变,就永远一样大 - 媒体查询中改
html { font-size: 14px; },所有rem字号立刻等比缩放,无需逐个调整 - 注意:
1rem不等于固定16px,而是等于当前生效的html字号——可能被clamp()、百分比或 JS 动态覆盖
padding/margin 里混用 em 和 rem 的坑
同一个单位,在不同属性里“看的对象”可能完全不同:
立即学习“前端免费学习笔记(深入)”;
-
.btn { font-size: 16px; padding: 0.5em 1em; }→ 这里的em看的是按钮自身的16px,所以 padding 是8px / 16px - 但如果按钮放在一个
.card { font-size: 12px; }里,且没重设font-size,那按钮继承12px,它的0.5empadding 就变成6px—— 值变了,但你可能根本没意识到 -
rem在padding里依然只认html,所以padding: 0.5rem在任何嵌套层级下都是同一物理尺寸
什么时候该切到哪个单位?
关键不是记规则,而是问一句:这个尺寸要不要随组件内部字体变化?
- 要随组件字体变(比如图标紧贴文字、行高)→ 用
em或无单位值(如line-height: 1.5) - 要全局一致、可批量缩放(标题、段落、间距体系)→ 用
rem - 既不想随父变、又不想绑根字号(比如按钮边框、小图标宽高)→ 直接用
px,别硬转
真正难的不是换算,是每次写 font-size 或 padding 时,心里得清楚这一行代码背后“它到底在看谁”。


















