PostCSS CSS转换工具插件:postcss‑px‑to‑viewport‑8‑plugin

介绍

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 语法规则

  1. ['*'] → 所有属性都转换
  2. ['width','height'] → 只转换width、height
  3. ['*','!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;
}

常见坑与最佳实践

  1. 第三方UI库单位错乱

    • 方案:exclude:[/node_modules/];如果UI库设计稿基准是375,利用viewportWidth函数动态返回不同设计稿宽度。
      viewportWidth: (file)=>{
      if(file.includes('node_modules/vant')) return 375
      return 750
      }
      
  2. 1px边框被转成vw,边框过细

    • 设置minPixelValue:1,≤1px不做转换。
  3. 字体跟随屏幕无限放大缩小

    • 方案1:propList:['*','!font‑size']字体不转换,写死px;
    • 方案2:fontViewportUnit:'rem'字体使用rem。
  4. 媒体查询内部px不转换

    • 将mediaQuery:true开启。
  5. vite不生效排查

    • postcss版本必须≥8.3.8;确认配置文件位置;缓存清除重启dev服务。