vw 适配 vs rem 适配
Vue 移动端做适配,传统方案是 lib-flexible + postcss-px2rem(动态调 html 根字号 + 转 rem)。但社区慢慢转向更纯粹的方案:用 vw 单位,完全不依赖运行时 JS。
vw(viewport width)是 CSS 单位,1vw = 视口宽度的 1%。比如视口 375px 宽,1vw = 3.75px。直接用 vw 替代 px,浏览器原生适配,不需要任何 JS 介入。
对比:
| 方案 | 原理 | 优劣 |
|---|---|---|
| lib-flexible + rem | JS 调 html font-size,CSS 用 rem | 依赖 JS,可手动控制根字号 |
| vw + postcss 自动转 | CSS 原生单位,无 JS | 大屏字体太大,需要额外限制 |

安装 postcss-px-to-viewport
npm:
npm i postcss-px-to-viewport -D
pnpm:
pnpm i -D postcss-px-to-viewport
Vue 3 项目推荐用维护更活跃的 postcss-px-to-viewport-8-plugin(支持 PostCSS 8):
pnpm i -D postcss-px-to-viewport-8-plugin
项目配置 postcss.config.js
项目根目录新建 postcss.config.js:
module.exports = {
plugins: {
// 处理大屏限制,vw 在 PC 上会让字体非常大,这个插件加 max-width 容器
'postcss-mobile-forever': {
appSelector: '#app',
viewportWidth: 375,
maxDisplayWidth: 640,
enableMediaQuery: true,
disableMobile: true
},
// 主力:px 转 vw
'postcss-px-to-viewport-8-plugin': {
unitToConvert: 'px',
viewportWidth: file => {
let num = 750
if (file.indexOf('van') > 0) {
num = 375 // Vant 组件库内部按 375 设计
}
return num
},
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: true,
replace: true,
exclude: [/node_modules/vant/i],
include: [],
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 1628
}
}
}
关键配置项详解
viewportWidth—— 设计稿宽度。不同来源的代码可以分别对待 —— Vant 内部按 375 设计,自家代码按 750 设计,这种就用函数动态返回。unitPrecision: 5—— vw 保留 5 位小数(1.46667vw),足够精确。propList: ['*']—— 所有 CSS 属性都转。可以排除某些属性(比如不转border-width):['*', '!border']。viewportUnit / fontViewportUnit: 'vw'—— 字体用 vw 还是 vmin,移动端竖屏用 vw 即可。selectorBlackList: []—— 选择器黑名单。比如['.pc-']表示 class 含pc-的不转。minPixelValue: 1—— 小于 1px 不转(避免 0.5px 这种 hairline 边框被转)。exclude—— 文件黑名单。常见做法:排除node_modules/vant因为 Vant 已经处理过自己的尺寸。
postcss-mobile-forever 解决大屏问题
纯 vw 适配有个尴尬:用户用 1920px 显示器全屏访问移动端页面,字体会变成超大,布局崩。
postcss-mobile-forever 解决这个问题:超过某个宽度时,把 #app 容器限制成固定 max-width,两边留白,移动端体验保持不变。
npm install --save-dev postcss postcss-mobile-forever
配置见上面的 postcss.config.js,关键参数:
appSelector: '#app'—— 你的根挂载点viewportWidth: 375—— 设计稿基准maxDisplayWidth: 640—— 超过这个宽度就限制 max-widthenableMediaQuery: true—— 加 media querydisableMobile: true—— 移动设备本身不动,正常 vw 适配
启用后,PC 浏览器全屏看 H5 项目时,内容会被限制在中间 640px 区域,两边背景留白,既不变形也不丑。
实际使用
配置完后,代码里照常写 px,构建时自动转 vw:
<style lang="less" scoped>
.card {
padding: 20px; /* → 2.667vw(750 设计稿) */
background: #fff;
border-radius: 8px;
}
.title {
font-size: 32px; /* → 4.267vw */
color: #333;
line-height: 1.5;
}
.price {
font-size: 28px;
color: #ee0a24;
margin-top: 12px;
}
</style>
关键技巧:跨 UI 库的尺寸基准切换
上面配置里这段精华:
viewportWidth: file => {
let num = 750
if (file.indexOf('van') > 0) {
num = 375
}
return num
}
原因:Vant 是按 375 设计稿做的内部样式。如果你的设计稿是 750,Vant 组件直接套进去会"小一半"。这段函数让 postcss 处理 Vant 文件时按 375 转换,处理你自己代码时按 750,各自正常显示。
同样的技巧适用于:NutUI、Varlet、其他移动 UI 库,看它们的设计稿基准是什么。
对比 rem 方案
选择建议:
- 新项目 → vw + postcss-px-to-viewport。配套
postcss-mobile-forever解决大屏问题。CSS 原生,无 JS 依赖,SSR 友好。 - 老项目用 rem,改不动 → 继续用 lib-flexible。改造成本不值得。
- 用 Tailwind / UnoCSS → 都不用。直接用框架自带的响应式类名。
相关延伸阅读:掘金 - vw 适配方案对比
—— 别看了 · 2026