rem不生效的根本原因是未动态设置html的font-size,它必须通过javascript监听resize和orientationchange事件,按设计稿宽度(如750px)与clientwidth比例实时计算并赋值document.documentelement.style.fontsize,否则rem仅为静态单位。

rem 不生效,根本原因是没动 html 的 font-size
很多人写了 font-size: 1.5rem,发现换手机、缩放页面、横竖屏切换后字号纹丝不动——这不是 rem 有问题,而是你只把它当“单位”用,忘了它本质是“相对值”。rem 永远等于当前 html 元素的 font-size,而这个值默认是浏览器设定的(通常 16px),不会自己随屏幕变。
所以第一步必须明确:所有适配逻辑都落在动态设置 document.documentElement.style.fontSize 上。不设它,rem 就是静态的、无响应的。
- 别在 CSS 里写死
html { font-size: 16px; },这等于放弃适配 - 别依赖用户系统字体设置或浏览器缩放——rem 不感知这些,除非你用
clamp()或监听resize+orientationchange - 设计稿宽度(如 750px)和代码里的基准值必须对齐:若设计稿宽 750px,推荐公式为
document.documentElement.style.fontSize = clientWidth / 750 * 100 + 'px',这样 1rem = 100px 在 750px 屏上,标注值除以 100 就是 rem 数
JS 动态设 font-size 的时机和防抖要点
直接在 DOMContentLoaded 里执行一次不够,iOS Safari 初次加载时常未触发 resize,安卓 WebView 对 resize 支持弱,横屏切换也可能漏掉事件。必须组合监听 + 立即执行 + 节流。
- 首次执行不能省:页面渲染前就得设好根字号,否则首屏元素按默认 16px 渲染,再改会闪一下
- 必须监听
resize和orientationchange,后者专治横竖屏切换失效问题 - 加节流(例如 100ms 内最多执行一次),避免快速拖拽窗口或双指缩放时频繁重排
-
clientWidth比innerWidth更稳妥——它不含滚动条宽度,且在移动端更接近真实视口逻辑像素;PC 端若有横向滚动条,偏差通常可接受
哪些 CSS 属性该用 rem,哪些坚决不能碰
rem 是缩放单位,不是万能单位。混用会导致尺寸叠加、比例错乱、小屏下不可见等实际问题。
- 该用:
font-size、width/height、margin/padding、border-radius - 不该用:
line-height(用无单位数值,如1.5,否则会随根字号二次放大) - 禁用:
border-width(比如border: 1px solid #ccc写成border: 0.01rem solid #ccc,小屏下可能缩到 0.2px 看不见) - 慎用:
background-size、box-shadow偏移、transform: scale()—— 这些属性本身已有缩放语义,再套 rem 容易失控
viewport 和 dpr 处理不干净,rem 会翻车
就算 font-size 算得准,viewport 配置错误或忽略设备像素比(dpr),也会让视觉效果严重失真。
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">必须存在,且不能被第三方库(如lib-flexible)重复注入 - 别用
font-size: 10vw直接设根字号——某些安卓 WebView 解析vw不准,导致字体忽大忽小 - 高清屏(dpr > 1)下,1px 边框发虚是常见问题,但不要用 rem 去“修”,应单独用伪元素 +
transform: scaleY(0.5)或box-shadow - 如果用了
postcss-pxtorem,务必确认rootValue与你 JS 中设置的基准一致(例如 JS 用 750 基准算出 1rem=100px,插件也要设rootValue: 100)
实际项目里最常被跳过的,是横竖屏切换后的 orientationchange 监听和 border 类属性的单位选择——这两处一漏,小屏设备上线就容易出视觉断裂或线条消失。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











