使用 postcss-px-to-viewport 插件解决移动端的适配方案。
原理是将固定的像素单位(px)转换为根据视窗大小缩放的单位(vw|vh),该插件实现的就是这一单位间的转化。
参考网址:
postcss-px-to-viewport 中文文档:https://github.com/evrone/postcss-px-to-viewport/blob/master/README_CN.md
该项目使用vue3+vite+typescript的技术栈进行创建。
安装vue3官网的安装项目步骤进行搭建即可,也就是使用 npm init vue@latest 进行项目搭建。
注意:
初始化的项目需要执行 npm install 去安装依赖,但是如果使用官方源安装很有可能会timeout,因此可以切换源为淘宝的镜像源。
ps: 如果源只是作用于该项目,可以在项目的跟路径下创建 .npmrc 的配置文件,在里面直接写入下面这条语句即可。
registry=https://registry.npm.taobao.org
安装移动端适配插件 postcss-px-to-viewport。
npm install postcss-px-to-viewport --save-dev
之后需要在vite的配置文件vite.config.ts中对postcss插件配置中进行相关配置,在最新版本的vite中,已经将postcss配置内嵌到css属性下面。
vite.config.ts中postcss基础配置如下:
// 引入 postcss-px-to-viewport 插件
import postcssPxToViewport from 'postcss-px-to-viewport'
export default defineConfig({
// ...
css: {
postcss: {
plugins: [
postcssPxToViewport({
unitToConvert: 'px', // 需要转换的单位 [常用]
viewportWidth: 375, // UI设计稿的宽度(还是需要根据实际情况进行调整,如果设置设计稿的宽度,会在移动端显示较小) [常用]
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
landscape: false, // 是否处理横屏情况
// landscapeUnit: 'px', // 横屏时使用的单位
// landscapeWidth: 750 // 横屏时使用的视口宽度
})
]
}
},
// ...
})
tip:
关于viewportWidth建议取设计稿的宽度,一般设计稿是750px,但是我们移动端屏幕一般宽度为375px(以iphone SE为基准),也就是屏幕实际1px对应设计稿2px,这样才能分配好设计稿的像素。
也就是说,如果我们使用750px作为viewportWidth,我们按照设计稿的实际像素布局页面,会自动将我们的像素除以2后才去适配屏幕实际像素,对于不同屏幕的缩放,缩小后的像素形成的图案其实会更加清晰。
就好比一个固定了宽高度的图片,放大后会失真,但缩小后则会更加清晰是一个道理;简单理解就是一个屏幕点上可以挤更多的像素点,形成的色彩会更佳鲜艳,丰富,上一更加清晰,反之,则失真模糊。
在使用这个插件,最常见的问题,其实是如何适配多个设计稿或多端。
多个设计稿一般只做移动端,使用750px的viewportWidth即可,因为UI一般也是按照这个尺寸设计,但是,如果使用了vant组件库,需要注意vant组件库的设计稿是375px。因此,需要进行适配。
多端这里主要指pc端(一般1920px的viewportWidth)和移动端(一般750px的viewportWidth),同样是针对两个不同的设计稿。因此,需要进行适配。
在我们上面搭建项目使用的是vite工具,针对的是vue3的情况;vue2结合了webpack其实更好处理这种使用了该插件的适配,而使用了vite搭建的vue3只能另辟蹊径。
1、移动端(750px)与vant(375px)适配
// 引入 postcss-px-to-viewport 插件
import postcssPxToViewport from 'postcss-px-to-viewport'
export default defineConfig({
// ...
css: {
postcss: {
postcssPxToViewport({
unitToConvert: 'px', // 需要转换的单位 [常用]
viewportWidth: 750, // UI设计稿的宽度(一般750, 需要根据实际情况进行调整,如果设置设计稿的宽度,会在移动端显示较小) [常用]
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/node_modules\/vant/, /src\/views\/view-375/], // 排除掉上面已经配置的插件
landscape: false, // 是否处理横屏情况
}),
postcssPxToViewport({
unitToConvert: 'px', // 需要转换的单位 [常用]
viewportWidth: 375,
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
landscape: false, // 是否处理横屏情况
})
}
},
// ...
})
上面的代码中,关于postcss适配写了两个插件(同一个插件配置了两次),执行插件的顺序是先执行最下面的,这样我先把全部文件使用375px适配了;之后在通过一个插件配置,在通过exclude属性排除了需要适配375px的目录或文件,给其他文件都适配750px即可。
pc端和移动端的适配也可以按照这个排除法的思路实现;如果是vue2+webpack搭建的项目,可以直接按照网上的在插件plugin直接传递一个回调函数,获取当前匹配的文件或目录名,动态的修改viewportWidth即可。
vue3+vite查看postcss的github官网,在issue中差不多可以找到上面这种解决方法,也有大佬直接二次封装去进行解决,主要针对移动端和pc端的适配,也可以考虑使用。