不能,vw/vh 不能直接替代 rem;必须配合 postcss-px-to-viewport 插件在构建时将 CSS 中的 px 按设计稿宽度(如 375 或 750)静态转换为 vw,viewportWidth 必须与设计稿严格一致,且仅作用于 CSS 文件,不处理 JS 内联样式或小数 px。

vw/vh 能直接替代 rem 吗?别信“一键替换”这种说法
不能。vw/vh 和 rem 的行为逻辑根本不同,不是改个单位就能跑通的。rem 是相对根字号的静态倍数,vw/vh 是实时响应视口尺寸的动态百分比。直接把 font-size: 1.6rem 换成 font-size: 4vw,在 320px 屏上会变成 12.8px,iOS 还会强制拉到 12px,文字糊成一团。
真正能替代 rem 的,是 postcss-px-to-viewport 插件 + 正确配置,它把你在 CSS 里写的 width: 20px,在构建时算成 width: 5.333vw(按 375 设计稿),这才是可落地的替换路径。
- viewportWidth 必须和设计稿宽度严格一致,错 1px 整体缩放就偏了
- 插件只处理 CSS 文件里的 px,JS 中拼的
style或内联style="width:20px"不会转换 - 不支持
border: 0.5px这类小数 px —— 构建时报 warning,得手动写成border: 1px或用background-image模拟
为什么必须用 postcss-px-to-viewport,而不是手写 vw?
因为人脑不适合做 100 / 375 * 120 这种计算。你写 width: 120px,插件自动转成 width: 32vw(375 设计稿下),这才是工程可行的写法。手写 vw 的后果:数值全是小数、维护成本爆炸、设计师改个尺寸你就得全重算。
关键参数只有三个:viewportWidth(设计稿宽度)、unitPrecision(小数位数,默认 5)、propList(哪些属性要转,比如 ['*'] 或 ['width', 'height', 'padding'])。
立即学习“前端免费学习笔记(深入)”;
-
viewportWidth: 750对应 @2x 设计稿;viewportWidth: 375对应 @1x,二者不能混用 -
unitPrecision: 3会让1px → 0.267vw,再小的精度对视觉无意义,反而增大 CSS 体积 - 慎用
propList: ['*'],border、box-shadow用 vw 容易失真,建议显式列出需要转换的属性
字体大小用 vw 会出什么问题?
font-size: 4vw 在 iPhone SE(320px)上是 12.8px,在 iPhone 14 Pro(430px)上是 17.2px —— 看似合理,但 iOS 强制最小字号为 12px,Android 部分系统也有类似限制,导致小屏实际显示比预期大,行高错乱,按钮文字撑出容器。
更稳妥的做法是用 clamp() 做兜底:font-size: clamp(14px, 4vw, 18px)。这行代码的意思是:最小 14px、理想值 4vw、最大 18px,浏览器自动插值,比一堆媒体查询轻量得多。
- 纯 vw 字体在折叠屏或横屏场景下可能过大,
clamp()能自然收敛 - 不要在
line-height上也套 vw —— 行高用无单位数值(如line-height: 1.5)更稳定 - 图标字体(如 iconfont)仍建议用 px 或 rem,vw 会导致矢量图标边缘模糊
vh 在 iOS Safari 里为啥总被刘海/安全区截掉?
因为 100vh 指的是整个 viewport 高度,但 iOS Safari 的地址栏、底部工具栏、刘海区域都算在 viewport 内,键盘弹出时 viewport 高度还会动态收缩。结果就是 height: 100vh 的弹层,底部被遮住一半。
解决方案不是放弃 vh,而是换用 dvh(dynamic viewport height):height: 100dvh。它始终取当前可视区域高度,不受地址栏收起/键盘弹出影响。不过注意:dvh 兼容性限于 Safari 16.4+(2023 年后)、Chrome 109+,老版本需回退到 100vh + JS 监听 resize 动态修正。
- 全屏背景图、登录页封面用
100dvh更稳;但导航栏高度这类固定结构,用rem或px反而更可控 - 不要在同一个组件里混用
vh和rem做 padding —— 渲染顺序差异会导致左右内边距视觉不等 - 滚动容器内慎用
vh,iOS Safari 滚动时会触发多次重排,造成卡顿
真正麻烦的不是怎么写 vw,而是设计稿交付时没人告诉你 viewportWidth 该填多少;也不是插件配不配得上,而是开发写完 padding: 10px 就去喝咖啡,忘了告诉设计师这个 px 会被转成多少 vw —— 协作断点,永远比技术断点更难修。


















