绝大多数响应式项目该用rem,因其将缩放控制权收归根元素,避免嵌套计算失控;rem使html{font-size}随视口动态变化,所有rem值自动等比响应,实现整站视觉比例一致缩放。

绝大多数响应式项目该用 rem,不是因为它“更现代”,而是它把缩放控制权收归根元素,避免嵌套计算失控。
为什么 rem 能让根字体缩放真正落地
响应式排版里所谓“根字体缩放”,本质是让 html { font-size } 随视口动态变化,后续所有 rem 值自动等比响应。这比手动写一堆媒体查询切 px 值轻量得多,也比靠 JS 每次重算所有尺寸稳定得多。
关键点在于:只要根字号变了,1.5rem 的边距、1.25rem 的圆角、1.125rem 的行高,全跟着变——你改一个地方,整站视觉比例就一致缩放。
常见错误现象:font-size: 16px 写死在 html 里,再套一层 @media (max-width: 768px) { html { font-size: 14px } },结果横屏切换时尺寸突变;或用 vw 直接设 font-size: 2.666vw,但在 iOS Safari 12 及更早版本里直接失效。
立即学习“前端免费学习笔记(深入)”;
- 推荐方案:用
clamp(14px, 2.5vw, 18px),平滑过渡,可读性可控,主流浏览器(Safari 13.1+、Chrome 88+)支持良好 - 兼容底线:若必须支持 Safari 12 或更低,JS 动态设置
document.documentElement.style.fontSize仍是唯一可靠路径,但记得加防抖、并确保首次渲染前执行 - 别在
html上写font-size: 62.5%这类“方便心算”的技巧——它依赖用户浏览器默认字号,且和系统字体缩放冲突,实测在 macOS + Safari 下容易失准
em 该用在哪?只限父字号强耦合的局部场景
em 不是错,只是适用面窄。它的价值不在全局缩放,而在“跟随当前文字节奏微调”。比如图标字体(icon-font)的 font-size 和 line-height 需与文本基线对齐,或按钮内边距想随文字大小同比例增减,这时用 em 更自然。
但一旦嵌套三层以上,font-size: 0.875em 就很难一眼看出最终像素值——它取决于当前元素自身的 font-size,而这个值又可能来自上层 em 或 rem 计算,调试时得逐层回溯。
- 安全用法:
line-height: 1.5(无单位)代替line-height: 1.5em;border-width: 0.0625em仅当明确需要边框粗细随文字缩放时才用 - 危险信号:在卡片组件里用
em设padding,但卡片标题用rem,正文又用px——这类混用会让间距逻辑彻底断裂 - 特别注意:
margin和padding用em时,参照的是该元素自身的font-size,不是父级;很多人误以为是父级,结果改了父容器字号,子元素内边距却没变,白白浪费半小时排查
混用 rem 和 em 的典型翻车现场
最常出问题的地方不是单位本身,而是同一类样式在不同组件里随意切换参照系。比如按钮的 padding 在 A 组件用 0.75rem,B 组件用 0.75em,C 组件又回到 12px,表面看数值接近,实际在缩放后完全错位。
更隐蔽的问题是:某个弹窗组件设置了 font-size: 0.875rem,里面所有用 em 的子元素(比如关闭按钮的 padding: 0.5em)就全部按 0.875 倍缩放,但开发者根本没意识到这层关系,以为只是“小一点”而已。
- 真实案例:某后台系统导航菜单用了
em控制二级菜单展开动画的max-height,结果用户调大系统字体后,菜单直接撑开溢出屏幕——因为max-height: 10em变成了原来的 1.5 倍 - 调试技巧:Chrome DevTools 的 Computed 面板里,点开任意
rem或em值,右侧会显示“resolved to xxx px”,点进去就能看到它到底参照了哪个元素的字号 - 底线原则:同一套设计系统里,
spacing、font-size、border-radius这三类值必须统一用一种单位,不许交叉;border、box-shadow、小图标尺寸这些固定精度需求的,一律用px
真正麻烦的从来不是选 rem 还是 em,而是改完根字号后,发现某个角落的 em 值突然放大两倍——它藏在第三层封装的组件里,连 class 名都看不出和字体有关。


















