rem和vw到底该用哪个做移动端适配?
最近在做一个移动端项目,UI给的设计稿是375px宽。我之前用rem配合js动态设置html的font-size,但听说现在主流都用vw了?试了下直接写width: 50vw确实方便,但有些老机型好像支持不好,而且和设计师沟通时单位换算也容易乱。到底该选哪种方案更稳妥?
我现在的rem方案是这样设置的:
(function() {
const baseSize = 37.5;
function setRem() {
const scale = document.documentElement.clientWidth / 10;
document.documentElement.style.fontSize = scale + 'px';
}
setRem();
window.addEventListener('resize', setRem);
})();
但感觉维护起来有点麻烦,想换vw又怕兼容性出问题,纠结死了……
平时写样式用rem,这样和设计师沟通也方便,本质上还是vw在驱动。
不过现在更推荐用
vw,前提是你要做两件事:第一,别直接裸写
50vw,得用 postcss-px-to-viewport 或 vite-plugin-px-to-viewport 这类工具自动转,否则手写 vw 容易错得离谱,而且和设计稿对不上;第二,老机型兼容性问题确实存在,比如 Android 4.4 以下的 WebView 对
vw支持很差,但这类机型现在基本可以忽略(除非你项目要适配政务/银行老设备,那得另说)。我之前做的一个金融类项目,UI 是 375 宽,用的是 postcss-px-to-viewport,配置里加了
viewportWidth: 375,exclude: //node_modules//防止第三方库被误转,最后 build 出来的 px 全部变成 vw,页面基本没抖动,连微信内置浏览器都能丝滑跑。不过要注意一点:
vw是基于视口宽度的,如果页面有横向滚动条或者 fixed 定位的元素参与布局,得小心边缘情况,比如某些机型底部导航栏会遮挡,可能得手动加个padding-bottom或env(safe-area-inset-bottom)来兜底,防止点击区被系统栏吃掉。最后提醒一句:如果项目用的是老框架(比如 jQuery Mobile 或者早期 hybrid 架构),别急着切 vw,先测测 WebView 渲染时机,有些壳里页面是异步注入的,vw 一上来可能算错,得加个
DOMContentLoaded后再触发重绘,防止注入后布局错乱。真要换,建议先拿一个子模块试水,跑完测试再全量切,别一上来就全改,改完不测等于埋雷。