在今天这篇文章中,我并不会在这里讲一些移动端视口的概念,包括物理像素和逻辑像素,理想视口,dpr等等等等,我只介绍这样一种很是不错的移动端适配方案:post-css-to-viewport,若是我说这种方案能解决98%以上的移动端布局痛点,我想整个掘金,应该没有人会反驳。css
在以前有一种流行已久的移动端适配方案,那就是rem,我想下面这两句代码,有很多老移动端都不会陌生:html
const deviceWidth = document.documentElement.clientWidth || document.body.clientWidth; document.querySelector('html').style.fontSize = deviceWidth / 7.5 + 'px';
没错,在那个移动端UI稿尺寸为750*1334满天飞的时代,这两句代码确实给开发者带来了很大的方便,这样设置根font-size后,px和rem的转换比例成了100, 为好比UI稿一个长宽分别为120px*40px,那么开发者对应的写成1.2rem*0.4rem就能够了vue
这种换算已是颇为方便,可是并不是全部的项目都能这样去设置一个方便换算的比例系数,当比例系数为100时,小数点往前面挪两位就好了,然而有的项目设置的换算系数千奇百怪,有50的,有16的,不少已经严重超出口算力所能及的范畴了。因此后来诞生的px-to-rem或者px2rem就是为了解决这个问题node
第一种方案是lib-flexible+postcss-pxtorem,在至关长一段时间里,这两个插件搭配都是解决移动端布局的神器,lib-flexible是阿里手淘系开源的一个库,用于设置font-size,同时处理一些窗口缩放的问题。其中一位主要贡献者正是阿里的大神winter。webpack
直到2020年的今天,我仍然能够说,lib-flexible+postcss-pxtorem是解决移动端布局的主流,可是咱们能够好好想想,它是否有什么不足?git
从我我的来讲,我认为它主要有如下两个不足:github
翻阅其github地址,能够看到这样一段有意思的话:web
第二种方案是viewport,postcss-px-to-viewport就是这样一款优秀的插件,它解决了以上提到的痛点,也知足以上提到的理想要求。它将px转换成视口单位vw,众所周知,vw本质上仍是一种百分比单位,100vw即等于100%,即window.innerWidthnpm
npm i postcss-px-to-viewport -D
module.exports = { plugins: { autoprefixer: {}, // 用来给不一样的浏览器自动添加相应前缀,如-webkit-,-moz-等等 "postcss-px-to-viewport": { unitToConvert: "px", // 要转化的单位 viewportWidth: 750, // UI设计稿的宽度 unitPrecision: 6, // 转换后的精度,即小数点位数 propList: ["*"], // 指定转换的css属性的单位,*表明所有css属性的单位都进行转换 viewportUnit: "vw", // 指定须要转换成的视窗单位,默认vw fontViewportUnit: "vw", // 指定字体须要转换成的视窗单位,默认vw selectorBlackList: ["wrap"], // 指定不转换为视窗单位的类名, minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换 mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false replace: true, // 是否转换后直接更换属性值 exclude: [/node_modules/], // 设置忽略文件,用正则作目录名匹配 landscape: false // 是否处理横屏状况 } } };
<div class="test-viewport">测试转换div>template><style lang="less" scoped>.test-viewport { width: 750px; height: 100px; font-size: 40px; text-align: center; line-height: 100px; background: #13b5b1; }style>
固然,当咱们引入一些第三方库的时候,好比vant,上面配置的exclude去掉,表示所有内容进行vw转换,会遇到这样的问题:windows
像这个TabBar,变得很是的小,被压扁了。
其实vant官网也是给出了关于viewport的适配方案,在github找一个名为vant-demo的项目,能够看到其配置以下:
很尴尬,vant团队的是根据375px的设计稿去作的,理想视口宽度为375px。
那么,咱们是否也要叫UI从新出一版375px的设计稿?
或者,咱们在书写的过程心算一下,全部标注的尺寸都除以2?
让咱们回到webpack自己,从新看一下这份.postc***c.js文件,它除了暴露一个对象,也能够暴露一个函数,不管暴露什么,在webpack运行时,都会被咱们配置的海量文件读取并执行。
暴露函数有一个好处,能够拿到webpack运行的当前执行文件的信息。
那么咱们能够有这样一个思路:若是读取的是vant相关的文件,viewportWidth就设为375,若是是其余的文件,咱们就按照咱们UI的宽度来设置viewportWidth,即750。
改写.postc***c.js文件配置以下:
const path = require('path');module.exports = ({ file }) => { const designWidth = file.dirname.includes(path.join('node_modules', 'vant')) ? 375 : 750; return { plugins: { autoprefixer: {}, "postcss-px-to-viewport": { unitToConvert: "px", viewportWidth: designWidth, unitPrecision: 6, propList: ["*"], viewportUnit: "vw", fontViewportUnit: "vw", selectorBlackList: [], minPixelValue: 1, mediaQuery: true, exclude: [], landscape: false } } } }
注意:这里使用path.join('node_modules', 'vant')是由于适应不一样的操做系统,在mac下结果为node_modules/vant,而在windows下结果为node_modules\vant
从新运行后发现,不只vant相关组件的单位被转换成了vw,并且其比例也是彻底正确的。