在今天這篇文章中,我並不會在這裏講一些移動端視口的概念,包括物理像素和邏輯像素,理想視口,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,並且其比例也是徹底正確的。