rem布局需JS动态设置根字号才生效;document.documentElement.clientWidth比window.innerWidth更可靠,因其排除滚动条和缩放干扰;baseFontSize与baseWidth应按设计稿比例设定,如750px稿配80px基础单位;resize须防抖,SPA路由切换需手动调用setRem。

rem布局本身不自动适配,必须靠JavaScript动态设置document.documentElement.style.fontSize才能生效;只写font-size: 1.5rem却不动根字号,和写px没区别。
为什么document.documentElement.clientWidth比window.innerWidth更可靠
因为window.innerWidth可能包含滚动条宽度(尤其在 macOS Safari 中),或受页面缩放(zoom ≠ 100%)干扰;而document.documentElement.clientWidth始终是视口内可用宽度,不含滚动条,也不受浏览器缩放影响,是计算等比缩放的真实基准。
- PC端高分屏、折叠屏、iPad Pro 等设备上,
window.innerWidth容易返回非整数或失真值 - 部分安卓 WebView 在横竖屏切换时,
window.innerWidth会延迟更新,但clientWidth实时准确 - 务必在
DOMContentLoaded阶段就调用一次,避免 FOUC(闪白)
setRem()函数里baseFontSize和baseWidth怎么定
这两个参数不是随便写的,它们决定了设计稿到代码的换算关系。例如设计稿是 750px 宽,标注中「按钮高度 80px」,你希望它在 750px 屏幕上正好是 1rem → 那就设baseWidth = 750、baseFontSize = 80;这样 80px ÷ 750px × 100% = 1rem,换算比就是80 / 750 ≈ 0.1067。
- 常见错误:把
baseFontSize设成 100 或 16 —— 这会让 1rem 太大,小屏上文字/控件直接溢出 - 推荐做法:让 1rem 对应设计稿中一个典型基础单位(如行高 44px、图标尺寸 24px),而非强行凑整
- 如果设计稿是 375px,建议
baseFontSize = 37.5(即 1rem = 37.5px),这样 100px 元素 =2.666rem,比用 100 更易估算
resize事件监听要防抖,否则 iOS Safari 会卡顿
原生resize在 iOS 上触发极频繁(尤其旋转时),连续设置fontSize会引发重排重绘风暴。不加控制的话,用户转屏瞬间页面可能假死 1–2 秒。
立即学习“前端免费学习笔记(深入)”;
- 简单防抖:用
setTimeout+ 标志位,延迟 100ms 执行,重复触发则清除前次定时器 - 更稳妥:改用
ResizeObserver监听document.documentElement,但需注意兼容性(IE 不支持,旧版 iOS Safari 需 polyfill) - 别忘了在 SPA 路由切换时手动调用一次
setRem(),Vue/React 中useEffect或mounted钩子里补上
真正难的不是写对那几行 JS,而是所有 rem 值都得按同一套比例换算,且设计师、前端、测试三方对「1rem = ? px」的理解必须完全一致;一旦某处漏了换算、或某人手写了px,整个等比体系就塌了一角。


















