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组件做适配