Vant 默认使用 px 作为样式单位,如果需要使用 viewport 单位 (vw, vh, vmin, vmax),推荐使用 postcss-px-to-viewport 进行转换。

# 1. 安装依赖 pnpm add -D postcss-px-to-viewport-8-plugin

安装 postcss-px-to-viewport 时,当前版本 v1.1.1 长期未更新,include 在 vue3 项目中实测不生效。

不设置或者将其设置成 include: undefined 如果控制台会报以下错误: postcss-px-to-viewport: postcss.plugin was deprecated .

Migration guide: 可以通过将 postcss-px-to-viewport 换成 postcss-px-to-viewport-8-plugin 解决

# 2. vite.config.ts 配置

import pxtovw from 'postcss-px-to-viewport-8-plugin';
css: {
    devSourcemap: true, // 在开发过程中是否启用 sourcemap。
    postcss: {
        plugins: [
            pxtovw({
                    unitToConvert: 'px', // 要转化的单位
                    viewportWidth: 375, // UI 设计稿的宽度
                    unitPrecision: 6, // 转换后的精度,即小数点位数
                    propList: ['*'], // 指定转换的 css 属性的单位,* 代表全部 css 属性的单位都进行转换
                    viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认 vw
                    fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认 vw
                    selectorBlackList: [], // 指定不转换为视窗单位的类名,
                    minPixelValue: 1, // 默认值 1,小于或等于 1px 则不进行转换
                    mediaQuery: true, // 是否在媒体查询的 css 代码中也进行转换,默认 false
                    //replace: true, // 是否直接更换属性值,而不添加备用属性
                    exclude: [/^(?!.*node_modules\/vant)(?!.*__uno\.css)/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
                    //include: undefined, // 如果设置了 include,那将只有匹配到的文件才会被转换
                    landscape: false // 是否处理横屏情况
            })
        ]
    }
},

注意

  • postcss-px-to-viewport内联css样式外联css样式内嵌css样式 有效,对 js 动态css 无效。 所以要动态改变 css 展示效果的话,要使用静态的 class 定义变化样式,通过 js 改变 dom 元素的 class实现样式变化
  • vue 模板中的 px 单位不会被转换,如需转换请使用 postcss-style-px-to-viewport 工具

# 3. 解决 vant 和 postcss-px-to-viewport 的配合

一般我们的设计稿都是 750,而 vant 的设计稿是 375,这就出现一种冲突。以 750 执行的话,则 vant 组件会变小

  • # postcss-px-to-viewport 移动端适配

在 vant 库里,我们依然用 375 的设计稿的宽度,其它的文件我们依然用 750 设计稿的宽度

//postcss.config.js
const path = require('path');
module.exports = ({webpack }) => {
    const designWidth = webpack.resourcePath.includes(path.join('node_modules', 'vant')) ? 375 : 750;
    return {
        plugins: {
            'postcss-px-to-viewport': {
                viewportWidth: designWidth, // 视窗的宽度,对应的是我们设计稿的宽度,一般是 750
                //viewportHeight: 1334, // 视窗的高度,根据 750 设备的宽度来指定,一般指定 1334,也可以不配置
            },
        }
    }
}
//vite.config.ts
pxToViewport({
    unitToConvert: 'px', // 要转化的单位
    viewportWidth: file => (join(file).includes(join('node_modules', 'vant')) ? 375 : 750), // UI 设计稿的宽度
    unitPrecision: 6, // 转换后的精度,即小数点位数
    propList: ['*'], // 指定转换的 css 属性的单位,* 代表全部 css 属性的单位都进行转换
    viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认 vw
    fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认 vw
    selectorBlackList: [], // 指定不转换为视窗单位的类名,
    minPixelValue: 1, // 默认值 1,小于或等于 1px 则不进行转换
    mediaQuery: true, // 是否在媒体查询的 css 代码中也进行转换,默认 false
    //replace: true, // 是否直接更换属性值,而不添加备用属性
    exclude: [/^(?!.*node_modules\/vant)(?!.*__uno\.css)/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
    //include: undefined, // 如果设置了 include,那将只有匹配到的文件才会被转换
    landscape: false // 是否处理横屏情况
})

注意:这里使用 path.join('node_modules', 'vant') 是因为适应不同的操作系统,在 mac 下结果为 node_modules/vant ,而在 windows 下结果为 node_modules\vant

Vant 组件的设计稿尺寸是 375px,可用通过覆盖:root 下的 Vant 的 css 变量中 px 单位的方式,对 Vant 组件做适配