背景
在做移动端自适应的需求的时候,px的单位是绝对单位,不适合做多屏幕的适配,这时候相对单位em,rem,vw,vh等这一类相对单位就各自发挥用处了,早前使用rem的方案居多,自从viewport的兼容性越来越强后社区开始流行vw这类单位做自适应,1vw为视口宽度的1%。UI设计稿还是会以px单位为主,这时候需要从px换算成vw,postcss推出了postcss-px-to-viewport这个插件来帮忙自动做转换,大家日常使用px单位,这个插件会自动转换成vw单位,用起来毫无成本,现在就来配置react项目下的postcss-px-to-viewport。
安装
postcss-px-to-viewport插件是建立在postcss已经安装的前提,目前官方的CRA脚手架已经默认安装了postcss8.x版本,但是最新的postcss-px-to-viewport插件和postcss8.x不兼容,所以要么将postcss版本降级到8.x一下,或者使用社区的兼容版本postcss-px-to-viewport-8-plugin,本人是使用了兼容版本,其次安装后还需要配置,本人这里使用craco进行webpack配置。
- 安装postcss-px-to-viewport-8-plugin
npm install postcss-px-to-viewport-8-plugin -D
- 配置postcss-px-to-viewport
在craco.config.js配置文件内添加以下配置:
style: {
postcss: {
mode: 'exclude',
loaderOptions: {
postcssOptions: {
ident: 'postcss',
plugins: [
[
'postcss-px-to-viewport-8-plugin',
{
unitToConvert: 'px', // 要转化的单位
viewportWidth: 375, // UI设计稿的宽度
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用 rem
fontViewportUnit: 'vw', // 字体使用的视口单位
unitPrecision: 13, // 指定`px`转换为视窗单位值的小数后 x位数
// propList: 当有些属性的单位我们不希望转换的时候,可以添加在数组后面,并在前面加上!号,如propList: ["*","!letter-spacing"],这表示:所有css属性的属性的单位都进行转化,除了letter-spacing的
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
// 转换的黑名单,在黑名单里面的我们可以写入字符串,只要类名包含有这个字符串,就不会被匹配。比如selectorBlackList: ['wrap'],它表示形如wrap,my-wrap,wrapper这样的类名的单位,都不会被转换
selectorBlackList: ['ignore'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
landscape: false, // 是否处理横屏情况
},
],
],
},
},
},
},
完整的截图:
postcss-px-to-viewport具体的配置项已经写好了注释,重新启动项目就可以生效:
注意:
配置后是所有px单位都会自动转换成vw,如果想要某些元素特殊不进行单位转换,除了在配置里面做文章之外,也可以将px单位大写为PX就可以禁止转换,cssinjs项目内也可以正常转换,但是内联样式不支持自动转换单位,这时候需要自己手动进行转换。此方案还存在一个问题,当视口到一定大小后希望固定单位不再进行转换,此方案就行不通,就算通过媒体查询固定了body的width,因为转换是依据视口的,视口仍然是变大的,所以里面的px但是还是会随着视口变大而变大,当在大屏幕上的时候各种尺寸就很不协调,类似于下图:
因此这个方案只适合移动端需求,如果还需要在pc端能展示,那还需要其他的方案,这里也推荐一篇文章,里面介绍了自适应的一些方案,供各位参考,也谢谢文章的作者:juejin.cn/post/686787…