介绍
postcss‑px‑to‑viewport‑8‑plugin 是 PostCSS 8 专用的 px 转视口单位插件,用于 H5/移动端自适应,编译阶段把 CSS 里的 px 自动转为 vw/vh/vmin/vmax,实现一套设计稿多设备适配。
背景
原版 postcss‑px‑to‑viewport 只支持 PostCSS7,升级 PostCSS8 会报 postcss.plugin was deprecated 废弃警告;本插件就是为兼容 PostCSS8 重写,API 和原版完全一致,可以直接替换。
适用场景:Vue3 + Vite、React + Vite、Webpack5 现代前端项目。
⚠️版本要求:
postcss >= 8.3.8,低版本不会转换单位。
安装
npm
npm install postcss-px-to-viewport-8-plugin -D
pnpm
pnpm add postcss-px-to-viewport-8-plugin -D
全部配置参数对照表
| 参数 | 类型 | 默认值 | 说明 | |
|---|---|---|---|---|
unitToConvert |
string | px |
需要转换的单位,一般就是px | |
viewportWidth |
number\ | Function | 320 |
设计稿宽度(750/375/1920);支持函数,传入文件路径,返回数值;返回undefined跳过该文件转换 |
unitPrecision |
number | 5 |
转换后保留小数位数 | |
propList |
string[] | ['*'] |
需要转换的属性;*全部;!xxx排除;例:['*','!border'] |
|
viewportUnit |
string | vw |
转换目标单位:vw/vh/vmin/vmax |
|
fontViewportUnit |
string | vw |
字体单独使用的视口单位 | |
selectorBlackList |
string[] | [] |
类名黑名单,匹配的类不转换;写完整类名,支持前缀匹配 | |
minPixelValue |
number | 1 |
小于等于该值的px不转换;1px边框场景常用 |
|
mediaQuery |
boolean | false |
是否转换媒体查询内部的px | |
replace |
boolean | true |
true直接替换px;false保留原px,追加转换后属性 | |
exclude |
RegExp\ | RegExp[] | undefined |
排除哪些文件不处理,正则匹配文件路径 |
include |
RegExp\ | RegExp[] | undefined |
只处理匹配的文件;exclude优先级高于include |
landscape |
boolean | false |
是否生成横屏媒体查询 | |
landscapeUnit |
string | vw |
横屏使用单位 | |
landscapeWidth |
number | 568 |
横屏基准视口宽度 |
propList 语法规则
['*']→ 所有属性都转换['width','height']→ 只转换width、height['*','!font-size']→ 全部属性,排除font‑size
两种配置方式
方式1:postcss.config.js(推荐)
独立配置文件,推荐
module.exports = {
plugins: {
autoprefixer: {},
'postcss-px-to-viewport-8-plugin': {
unitToConvert: 'px',
viewportWidth: 750, // 设计稿750
unitPrecision: 4,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: ['.no‑convert'], // class="no‑convert"不转换
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: [/node_modules/] // 不转换第三方组件库
}
}
}
方式2:Vite 内联配置 vite.config.ts
import { defineConfig } from 'vite'
import postcsspxtoviewport8plugin from 'postcss-px-to-viewport-8-plugin'
export default defineConfig({
css: {
postcss: {
plugins: [
postcsspxtoviewport8plugin({
viewportWidth: 750,
unitPrecision:4,
propList:['*'],
exclude:[/node_modules/]
})
]
}
}
})
代码忽略转换
局部不转换px
1. 当前属性不转换
.box {
width:100px; /* px-to-viewport-ignore */
}
2. 下一行不转换
.box {
/* px-to-viewport-ignore-next */
height:200px;
}
转换示例
输入:
.demo {
width:750px;
font-size:28px;
}
输出(viewportWidth=750):
.demo {
width:100vw;
font-size:3.73333vw;
}
常见坑与最佳实践
第三方UI库单位错乱
- 方案:
exclude:[/node_modules/];如果UI库设计稿基准是375,利用viewportWidth函数动态返回不同设计稿宽度。viewportWidth: (file)=>{ if(file.includes('node_modules/vant')) return 375 return 750 }
- 方案:
1px边框被转成vw,边框过细
- 设置
minPixelValue:1,≤1px不做转换。
- 设置
字体跟随屏幕无限放大缩小
- 方案1:
propList:['*','!font‑size']字体不转换,写死px; - 方案2:
fontViewportUnit:'rem'字体使用rem。
- 方案1:
媒体查询内部px不转换
- 将
mediaQuery:true开启。
- 将
vite不生效排查
- postcss版本必须≥8.3.8;确认配置文件位置;缓存清除重启dev服务。