em的值等于当前元素的font-size,需逐层向上追溯父级font-size直至绝对值;rem则始终基于html根元素font-size,不受嵌套影响,适合全局统一控制。

em在嵌套中怎么算出错的
em的值不是固定数字,它永远等于「当前元素的font-size」。问题出在:这个font-size本身可能就是用em设的——于是你得一层层往上翻父级的计算值,直到找到一个绝对值(比如px或浏览器默认16px)才算完。
常见错误现象:.card { font-size: 1.2em; },而它的父容器是font-size: 1.5rem(即24px),那.card实际字号就是24px × 1.2 = 28.8px;但如果父容器又被设成font-size: 0.8em,你就得再往前推一辈……调试时打开开发者工具看computed font-size,经常发现写着“14.4px”,但谁也说不清这0.9倍到底是哪一层漏掉的。
- 父元素用
font-size: 0或font-size: 0.625em(即10px),子元素1.2em就变成12px,而非预期的19.2px - 组件库里按钮用了
font-size: 0.875em,但嵌在弹窗里时弹窗父级被JS临时缩放为font-size: 0.9em,按钮文字就莫名变小 - 用
%或em混设line-height(如line-height: 1.5em),会继承父级font-size而非自身,导致行高悬空
rem为什么能绕过嵌套陷阱
rem只认html元素的font-size,不管你在DOM树第几层、父级有没有改字号,1.2rem永远是html字号 × 1.2。这是真正意义上的“单点控制”。
使用场景很明确:全局字号、间距、圆角、阴影偏移等需要跨组件对齐的尺寸。比如所有卡片标题统一用font-size: 1.25rem,哪怕它嵌在modal、sidebar、tooltip里,显示效果都一致。
立即学习“前端免费学习笔记(深入)”;
- 别把rem当“更高级的px”来用——如果
html { font-size: 16px; }写死,那1rem就是16px,和px没区别,失去响应意义 - 真要响应式,必须让
html的font-size动起来:用clamp()、媒体查询或JS动态计算,否则rem只是个带根号的px - 检查运行时根字号是否符合预期:加一行
console.log(parseFloat(getComputedStyle(document.documentElement).fontSize)),别信配置文件里的注释
什么时候还非得用em
em不是该被淘汰,而是该被精准限制使用范围。它唯一不可替代的场景,是「需要跟随文字等比缩放」的局部属性。
比如图标字体(icon-font)对齐文本基线:.icon { font-size: 0.8em; vertical-align: middle; }——这里0.8em是相对于父文字大小的,换字号时图标自动缩放,保持视觉比例;又比如border-width: 0.1em,边框粗细随文字变大而变粗,适合强调型按钮。
- 禁止在组件内部混用em和rem定义字号:一个按钮同时有
font-size: 0.875rem和padding: 0.5em,padding会随按钮自身字号变,但字号又受根字号控,逻辑断裂 - em用于
margin/padding可以,但前提是该组件的font-size是固定值(如px或rem),否则padding也会飘 - 用em设
line-height风险极高,一律改用无单位数值(如line-height: 1.5)
PostCSS或设计稿换算时最容易踩的坑
很多团队用postcss-pxtorem把16px转成1rem,结果上线后所有20rem变成200px——因为JS脚本把html的font-size设成了10px(为方便心算),而插件仍按16px基准转,编译结果和运行时不匹配。
- 确认
postcss-pxtorem的rootValue配置和实际运行时document.documentElement.style.fontSize完全一致 - 设计稿按375px宽、基准字号10px标注?那代码里
html { font-size: 10px; }必须同步,不能只靠JS动态算 - 用
clamp(14px, 2.5vw, 18px)设根字号时,别指望PostCSS能正确解析vw值——它只处理静态数字,这类动态值必须手写或用JS兜底
最麻烦的不是不会算,而是忘了“em的基准在父级,rem的基准在html,而html的font-size可能被任何JS覆盖”。每次改完字号相关逻辑,务必在真机横竖屏切换、系统字体放大设置下验证一遍。


















