rem适配时页面元素在不同手机上缩放比例不一致怎么办?
我用rem方案开发移动端时,设置了根字体大小根据屏幕宽度计算,但iPhone12和小米11上按钮大小明显不一样,html{font-size:50px}明明是动态计算的啊…
代码是这样写的:
function setRem() {
const width = document.documentElement.clientWidth;
document.documentElement.style.fontSize = width / 10 + 'px';
}
window.addEventListener('resize', setRem);
setRem();
但在真机调试时发现,同样10rem宽的div,iPhone显示比预期小很多,而安卓机型又偏大,这是哪里出问题了?
第一个,iOS的最小字体限制。
Safari浏览器有个很坑的设定——最小字体不能小于12px(有些版本是16px)。你算一下,iPhone12的宽度是390px,除以10等于39px,这个是大于12px的,理论上不应该触发。但问题在于你的代码没有在页面加载开始时就执行,如果有任何延迟或者某些情况导致计算结果偏小,就会中招。
解决办法是在CSS里加一行:
html {
-webkit-text-size-adjust: 100%;
font-size: 16px; / 兜底值 /
}
第二个,更关键的问题——dpr(设备像素比)没考虑。
iPhone12的dpr是3,小米的dpr也可能是3或者2.75。这意味着375px的宽度在iPhone上实际上对应1125个物理像素。你按CSS像素算出来的10rem,在iPhone上会显得更小。
正确做法是根据dpr来调整,或者直接用这个更稳健的方案:
function setRem() {
const width = document.documentElement.clientWidth;
const dpr = window.devicePixelRatio || 1;
const scale = 1 / dpr;
const meta = document.querySelector('meta[name="viewport"]');
meta.setAttribute('content',
width=device-width, initial-scale=${scale}, maximum-scale=${scale}, user-scalable=0);document.documentElement.style.fontSize = width / 10 + 'px';
}
简单说就是让viewport的initial-scale根据dpr动态调整,这样CSS像素和物理像素的对应关系就一致了。
还有一个可能——你的meta标签可能没写或者写错了,确保要有:
你先检查下这个meta标签在不在,然后试试上面的dpr处理方案,基本就能解决。
解决方法其实不复杂,核心是把 dpr 考虑进去。你可以用 window.devicePixelRatio 获取设备的像素比,然后调整你的 rem 计算逻辑。不过更推荐的做法是借助 flexible.js 或者 viewport 单位来处理适配问题,少走弯路。
如果你不想引入额外库,可以改成这样:
这里的关键点是动态设置 viewport 的缩放比例,让不同设备的显示效果尽量一致。另外提醒一下,别忘了测试极端分辨率的设备,比如一些奇葩的小屏机或者折叠屏,它们可能会暴露新的问题。
如果觉得 rem 还是麻烦,也可以试试 vw/vh 单位配合 postcss-px-to-viewport 插件,效果也不错,省得自己折腾。总之多试几种方案,找到最适合你们项目的那个。