postcss-px-to-viewport 是移动端适配 vw 方案的唯一合理选择,因其专为视口单位转换设计;viewportWidth 必须设为设计稿宽度(如375或750),unitPrecision 建议设为3以平衡精度与兼容性。

PostCSS插件选哪个:postcss-px-to-viewport 还是 postcss-pxtorem?
移动端适配用 vw 单位时,postcss-px-to-viewport 是唯一合理选择。postcss-pxtorem 专为 rem 设计,强行改配置也不会输出 vw,反而导致单位混乱或转换失效。
注意:postcss-px-to-viewport 的默认行为是把所有 px 都转,包括 border、font-size、padding 等,但实际项目中常需保留某些值(比如 1px 边框),这点必须提前配置好,否则上线后视觉出错。
关键配置项怎么设:viewportWidth 和 unitPrecision 是什么?
viewportWidth 必须设成设计稿宽度(如 375 或 750),它决定换算基准——不是设备屏幕宽,也不是 document.documentElement.clientWidth,而是你拿到的 UI 设计图的 px 宽度。设错会导致所有尺寸缩放失真。
unitPrecision 控制小数位数,默认是 5,但多数项目用 3 就够了;设太小(如 1)会让 12.678px → 12.7vw,影响布局精度;设太大(如 6)则生成冗余小数,无实际意义,还可能触发 Safari 对超长小数的渲染异常。
立即学习“前端免费学习笔记(深入)”;
常用配置示例:
module.exports = {
plugins: {
'postcss-px-to-viewport': {
viewportWidth: 375,
unitPrecision: 3,
viewportUnit: 'vw',
selectorBlackList: ['.ignore', '.hairlines'],
minPixelValue: 1,
mediaQuery: false
}
}
}哪些 px 不该转?用 selectorBlackList 和 propBlackList 区分场景
直接写 1px 的边框,在高倍屏上会变细甚至看不见,所以通常要转成 0.026666vw(以 375 设计稿为例)来实现“物理像素边框”。但有些情况确实不能转:
- 第三方 UI 库的内联样式(如
vant的border: 1px solid #eee),改不了源码,只能加selectorBlackList: ['.van-button'] - CSS 变量定义里的 px(如
--border-width: 1px),应放入propBlackList: ['border', 'border-top'],避免被转成vw后无法参与计算 - 媒体查询里的
max-width: 750px,必须设mediaQuery: true才能生效,否则会被忽略
为什么 build 后没变化?检查 PostCSS 加载顺序和文件范围
常见静默失败原因有三个:
- PostCSS 配置没被 Webpack/Vite 正确读取——Vite 用户要确认
vite.config.ts中是否在css.postcss下写了配置,而不是丢在根目录postcss.config.js里(Vite 默认不读) - SCSS/SASS 文件未被 PostCSS 处理——Webpack 要确保
postcss-loader在css-loader之后、sass-loader之前;Vite 则默认支持,但若用了@import引入外部 CSS,那些文件可能绕过处理 - Vue 单文件组件中
<style scoped></style>内的 px 被转了,但父组件传入的 class 名带px(如class="icon-16px")不会被处理——PostCSS 只处理 CSS 内容,不碰 HTML 类名或 JS 字符串
最简单的验证方式:在任意 .vue 或 .css 文件里写一句 div { width: 100px; },看编译后是否变成 width: 26.667vw;。不是?那就先停在这一步排查配置加载问题。
真正麻烦的是混合单位场景——比如 calc(100% - 20px),插件默认不处理函数内表达式,得手动改成 calc(100% - 5.333vw) 或用 ignoreComment 注释跳过。这个细节,上线前很容易漏掉。


















