postcss

有關(guān)于移動端的適配布局一直以來都是眾說紛紜蘸际,對應的解決方案也是有很多種。在《使用Flexible實現(xiàn)手淘H5頁面的終端適配》提出了Flexible的布局方案长赞,隨著viewport單位越來越受到眾多瀏覽器的支持置谦,因此在《再聊移動端頁面的適配》一文中提出了vw來做移動端的適配問題。到目前為止不管是哪一種方案,都還存在一定的缺陷甚淡。言外之意,還沒有哪一個方案是完美的捅厂。

事實上真的不完美贯卦?其實不然。最近為了新項目中能更完美的使用vw來做移動端的適配焙贷。探討出一種能解決不兼容viewport單位的方案撵割。今天整理一下,與大家一起分享辙芍。如果方案中存在一定的缺陷啡彬,歡迎大家一起拍正羹与。

準備工作

對于Flexible或者說vw的布局,其原理不在這篇文章進行闡述庶灿。如果你想追蹤其中的原委纵搁,強烈建議你閱讀早前整理的文章《使用Flexible實現(xiàn)手淘H5頁面的終端適配》和《再聊移動端頁面的適配》。

說句題外話往踢,由于Flexible的出現(xiàn)腾誉,也造成很多同學對rem的誤解。正如當年大家對div的誤解一樣峻呕。也因此利职,大家都覺得rem是萬能的,他能直接解決移動端的適配問題瘦癌。事實并不是如此猪贪,至于為什么,我想大家應該去閱讀flexible.js源碼佩憾,我相信你會明白其中的原委。

回到我們今天要聊的主題干花,怎么實現(xiàn)vw的兼容問題妄帘。為了解決這個兼容問題,我將借助Vue官網(wǎng)提供的構(gòu)建工程以及一些PostCSS插件來完成池凄。在繼續(xù)后面的內(nèi)容之前抡驼,需要準備一些東西:

NodeJs

NPM

Webpack

Vue-cli

postcss-import

postcss-url

postcss-aspect-ratio-mini

postcss-cssnext

autoprefixer

postcss-px-to-viewport

postcss-write-svg

cssnano

postcss-viewport-units

Viewport Units Buggyfill

對于這些起什么作用,先不闡述肿仑,后續(xù)我們會聊到上述的一些東西致盟。

使用Vue-cli來構(gòu)建項目

對于NodeJsNPMWebpack相關(guān)介紹尤慰,大家可以查閱其對應的官網(wǎng)馏锡。這里默認你的系統(tǒng)環(huán)境已經(jīng)安裝好Nodejs、NPM和Webpack伟端。我的系統(tǒng)目前使用的Node版本是v9.4.0杯道;NPM的版本是v5.6.0。事實上责蝠,這些都并不重要党巾。

使用Vue-cli構(gòu)建項目

為了不花太多的時間去深入的了解Webpack(Webpack對我而言,太蛋疼了)霜医,所以我直接使用Vue-cli來構(gòu)建自己的項目齿拂,因為我一般使用Vue來做項目。如果你想深入的了解Webpack肴敛,建議你閱讀下面的文章:

Webpack文檔

Awesome Webpack

Webpack 教程資源收集

Vue+Webpack開發(fā)可復用的單頁面富應用教程

接下來的內(nèi)容署海,直接使用Vue官方提供的Vue-cli的構(gòu)建工具來構(gòu)建Vue項目吗购。首先需要安裝Vue-cli:

$ npm install-g vue-cli

全局先安裝Vue-cli,假設你安裝好了Vue-cli叹侄。這樣就可以使用它來構(gòu)建項目:

vueinitwebpack vw-layout

根據(jù)命令提示做相應的操作:

image

進入到剛創(chuàng)建的vw-layout:

cd vw-layout

然后執(zhí)行:

npm run dev

在瀏覽器執(zhí)行http://localhost:8080巩搏,就可以看以默認的頁面效果:

image

以前的版本需要先執(zhí)行npm i安裝項目需要的依賴關(guān)系。現(xiàn)在新版本的可以免了趾代。

這時贯底,可以看到的項目結(jié)構(gòu)如下:

使用Vue-cli構(gòu)建項目

安裝PostCSS插件

通過Vue-cli構(gòu)建的項目,在項目的根目錄下有一個.postcssrc.js撒强,默認情況下已經(jīng)有了:

module.exports={"plugins":{"postcss-import":{},"postcss-url":{},"autoprefixer":{}}}

對應我們開頭列的的PostCSS插件清單禽捆,現(xiàn)在已經(jīng)具備了:

postcss-import

postcss-url

autoprefixer

簡單的說一下這幾個插件。

postcss-import

postcss-import相關(guān)配置可以點擊這里飘哨。目前使用的是默認配置胚想。只在.postcssrc.js文件中引入了該插件。

postcss-import主要功有是解決@import引入路徑問題芽隆。使用這個插件浊服,可以讓你很輕易的使用本地文件、node_modules或者web_modules的文件胚吁。這個插件配合postcss-url讓你引入文件變得更輕松牙躺。

postcss-url

postcss-url相關(guān)配置可以點擊這里。該插件主要用來處理文件腕扶,比如圖片文件孽拷、字體文件等引用路徑的處理。

在Vue項目中半抱,vue-loader已具有類似的功能脓恕,只需要配置中將vue-loader配置進去。

autoprefixer

autoprefixer插件是用來自動處理瀏覽器前綴的一個插件窿侈。如果你配置了postcss-cssnext炼幔,其中就已具備了autoprefixer的功能。在配置的時候史简,未顯示的配置相關(guān)參數(shù)的話江掩,表示使用的是Browserslist指定的列表參數(shù),你也可以像這樣來指定last 2 versions?或者?> 5%乘瓤。

如此一來环形,你在編碼時不再需要考慮任何瀏覽器前綴的問題,可以專心擼碼衙傀。這也是PostCSS最常用的一個插件之一抬吟。

其他插件

Vue-cli默認配置了上述三個PostCSS插件,但我們要完成vw的布局兼容方案统抬,或者說讓我們能更專心的擼碼火本,還需要配置下面的幾個PostCSS插件:

postcss-aspect-ratio-mini

postcss-px-to-viewport

postcss-write-svg

postcss-cssnext

cssnano

postcss-viewport-units

要使用這幾個插件危队,先要進行安裝:

npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg postcss-cssnext postcss-viewport-units cssnano --S

安裝成功之后,在項目根目錄下的package.json文件中钙畔,可以看到新安裝的依賴包:

"dependencies": {? ? "cssnano": "^3.10.0",? ? "postcss-aspect-ratio-mini": "0.0.2",? ? "postcss-cssnext": "^3.1.0",? ? "postcss-px-to-viewport": "0.0.3",? ? "postcss-viewport-units": "^0.1.3",? ? "postcss-write-svg": "^3.0.1",? ? "vue": "^2.5.2",? ? "vue-router": "^3.0.1"},

接下來在.postcssrc.js文件對新安裝的PostCSS插件進行配置:

module.exports={"plugins":{"postcss-import":{},"postcss-url":{},"postcss-aspect-ratio-mini":{},"postcss-write-svg":{utf8:false},"postcss-cssnext":{},"postcss-px-to-viewport":{viewportWidth:750,// (Number) The width of the viewport.viewportHeight:1334,// (Number) The height of the viewport.unitPrecision:3,// (Number) The decimal numbers to allow the REM units to grow to.viewportUnit:'vw',// (String) Expected units.selectorBlackList:['.ignore','.hairlines'],// (Array) The selectors to ignore and leave as px.minPixelValue:1,// (Number) Set the minimum pixel value to replace.mediaQuery:false// (Boolean) Allow px to be converted in media queries.},"postcss-viewport-units":{},"cssnano":{preset:"advanced",autoprefixer:false,"postcss-zindex":false}}}

特別聲明:由于cssnext和cssnano都具有autoprefixer,事實上只需要一個茫陆,所以把默認的autoprefixer刪除掉,然后把cssnano中的autoprefixer設置為false擎析。對于其他的插件使用簿盅,稍后會簡單的介紹。

由于配置文件修改了揍魂,所以重新跑一下npm run dev桨醋。項目就可以正常看到了现斋。接下來簡單的介紹一下后面安裝的幾個插件的作用喜最。

postcss-cssnext

postcss-cssnext其實就是cssnext。該插件可以讓我們使用CSS未來的特性庄蹋,其會對這些特性做相關(guān)的兼容性處理瞬内。其包含的特性主要有:

postcss-cssnext

有關(guān)于cssnext的每個特性的操作文檔,可以點擊這里瀏覽限书。

cssnano

cssnano主要用來壓縮和清理CSS代碼虫蝶。在Webpack中,cssnano和css-loader捆綁在一起蔗包,所以不需要自己加載它秉扑。不過你也可以使用postcss-loader顯式的使用cssnano慧邮。有關(guān)于cssnano的詳細文檔调限,可以點擊這里獲取。

在cssnano的配置中误澳,使用了preset: "advanced"耻矮,所以我們需要另外安裝:

npm i cssnano-preset-advanced --save-dev

cssnano集成了一些其他的PostCSS插件,如果你想禁用cssnano中的某個插件的時候忆谓,可以像下面這樣操作:

"cssnano":{autoprefixer:false,"postcss-zindex":false}

上面的代碼把autoprefixer和postcss-zindex禁掉了裆装。前者是有重復調(diào)用,后者是一個討厭的東東倡缠。只要啟用了這個插件哨免,z-index的值就會重置為1。這是一個天坑昙沦,千萬記得將postcss-zindex設置為false琢唾。

postcss-px-to-viewport

postcss-px-to-viewport插件主要用來把px單位轉(zhuǎn)換為vw、vh盾饮、vmin或者vmax這樣的視窗單位采桃,也是vw適配方案的核心插件之一懒熙。

在配置中需要配置相關(guān)的幾個關(guān)鍵參數(shù):

"postcss-px-to-viewport":{viewportWidth:750,// 視窗的寬度,對應的是我們設計稿的寬度普办,一般是750viewportHeight:1334,// 視窗的高度工扎,根據(jù)750設備的寬度來指定,一般指定1334衔蹲,也可以不配置unitPrecision:3,// 指定`px`轉(zhuǎn)換為視窗單位值的小數(shù)位數(shù)(很多時候無法整除)viewportUnit:'vw',// 指定需要轉(zhuǎn)換成的視窗單位肢娘,建議使用vwselectorBlackList:['.ignore','.hairlines'],// 指定不轉(zhuǎn)換為視窗單位的類,可以自定義踪危,可以無限添加,建議定義一至兩個通用的類名minPixelValue:1,// 小于或等于`1px`不轉(zhuǎn)換為視窗單位蔬浙,你也可以設置為你想要的值mediaQuery:false// 允許在媒體查詢中轉(zhuǎn)換`px`}

目前出視覺設計稿,我們都是使用750px寬度的贞远,那么100vw = 750px畴博,即1vw = 7.5px。那么我們可以根據(jù)設計圖上的px值直接轉(zhuǎn)換成對應的vw值蓝仲。在實際擼碼過程俱病,不需要進行任何的計算,直接在代碼中寫px袱结,比如:

.test{border:.5px solid black;border-bottom-width:4px;font-size:14px;line-height:20px;position:relative;}[w-188-246]{width:188px;}

編譯出來的CSS:

.test{border:.5px solid #000;border-bottom-width:.533vw;font-size:1.867vw;line-height:2.667vw;position:relative;}[w-188-246]{width:25.067vw;}

在不想要把px轉(zhuǎn)換為vw的時候亮隙,首先在對應的元素(html)中添加配置中指定的類名.ignore或.hairlines(.hairlines一般用于設置border-width:0.5px的元素中):

<divclass="box ignore"></div>

寫CSS的時候:

.ignore{margin:10px;background-color:red;}.box{width:180px;height:300px;}.hairlines{border-bottom:0.5px solid red;}

編譯出來的CSS:

.box{width:24vw;height:40vw;}.ignore{margin:10px;/*.box元素中帶有.ignore類名,在這個類名寫的`px`不會被轉(zhuǎn)換*/background-color:red;}.hairlines{border-bottom:0.5px solid red;}

上面解決了px到vw的轉(zhuǎn)換計算垢夹。那么在哪些地方可以使用vw來適配我們的頁面溢吻。根據(jù)相關(guān)的測試:

容器適配,可以使用vw

文本的適配果元,可以使用vw

大于1px的邊框促王、圓角、陰影都可以使用vw

內(nèi)距和外距而晒,可以使用vw

postcss-aspect-ratio-mini

postcss-aspect-ratio-mini主要用來處理元素容器寬高比蝇狼。在實際使用的時候,具有一個默認的結(jié)構(gòu)

<divaspectratio><divaspectratio-content></div></div>

在實際使用的時候倡怎,你可以把自定義屬性aspectratio和aspectratio-content換成相應的類名迅耘,比如:

<divclass="aspectratio">? ? <divclass="aspectratio-content"></div></div>

我個人比較喜歡用自定義屬性,它和類名所起的作用是同等的监署。結(jié)構(gòu)定義之后颤专,需要在你的樣式文件中添加一個統(tǒng)一的寬度比默認屬性:

[aspectratio]{position:relative;}[aspectratio]::before{content:'';display:block;width:1px;margin-left:-1px;height:0;}[aspectratio-content]{position:absolute;top:0;left:0;right:0;bottom:0;width:100%;height:100%;}

如果我們想要做一個188:246(188是容器寬度,246是容器高度)這樣的比例容器钠乏,只需要這樣使用:

[w-188-246]{aspect-ratio:'188:246';}

有一點需要特別注意:aspect-ratio屬性不能和其他屬性寫在一起栖秕,否則編譯出來的屬性只會留下aspect-ratio的值,比如:

<divaspectratiow-188-246class="color"></div>

編譯前的CSS如下:

[w-188-246]{width:188px;background-color:red;aspect-ratio:'188:246';}

編譯之后:

[w-188-246]:before{padding-top:130.85106382978725%;}

主要是因為在插件中做了相應的處理缓熟,不在每次調(diào)用aspect-ratio時累魔,生成前面指定的默認樣式代碼摔笤,這樣代碼沒那么冗余。所以在使用的時候垦写,需要把width和background-color分開來寫:

[w-188-246]{width:188px;background-color:red;}[w-188-246]{aspect-ratio:'188:246';}

這個時候吕世,編譯出來的CSS就正常了:

[w-188-246]{width:25.067vw;background-color:red;}[w-188-246]:before{padding-top:130.85106382978725%;}

有關(guān)于寬高比相關(guān)的詳細介紹,如果大家感興趣的話梯投,可以閱讀下面相關(guān)的文章:

CSS實現(xiàn)長寬比的幾種方案

容器長寬比

Web中如何實現(xiàn)縱橫比

實現(xiàn)精準的流體排版原理

目前采用PostCSS插件只是一個過渡階段命辖,在將來我們可以直接在CSS中使用aspect-ratio屬性來實現(xiàn)長寬比。

postcss-write-svg

postcss-write-svg插件主要用來處理移動端1px的解決方案分蓖。該插件主要使用的是border-image和background來做1px的相關(guān)處理尔艇。比如:

@svg1px-border{height:2px;@rect{fill:var(--color,black);width:100%;height:50%;}}.example{border:1px solid transparent;border-image:svg(1px-borderparam(--color #00b1ff))2 2 stretch;}

編譯出來的CSS:

.example{border:1px solid transparent;border-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E")2 2 stretch;}

上面演示的是使用border-image方式,除此之外還可以使用background-image來實現(xiàn)么鹤。比如:

@svgsquare{@rect{fill:var(--color,black);width:100%;height:100%;}}#example{background:whitesvg(squareparam(--color #00b1ff));}

編譯出來就是:

#example{background:whiteurl("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2300b1ff' width='100%25' height='100%25'/%3E%3C/svg%3E");}

解決1px的方案除了這個插件之外终娃,還有其他的方法≌籼穑可以閱讀前期整理的《再談Retina下1px的解決方案》一文棠耕。

特別聲明:由于有一些低端機對border-image支持度不夠友好,個人建議你使用background-image的這個方案柠新。

CSS Modules

Vue中的vue-loader已經(jīng)集成了CSS Modules的功能窍荧,個人建議在項目中開始使用CSS Modules。特別是在Vue和React的項目中恨憎,CSS Modules具有很強的優(yōu)勢和靈活性蕊退。建議看看CSS In JS相關(guān)的資料。在Vue中憔恳,使用CSS Modules的相關(guān)文檔可以閱讀Vue官方提供的文檔《CSS Modules》瓤荔。

postcss-viewport-units

postcss-viewport-units插件主要是給CSS的屬性添加content的屬性,配合viewport-units-buggyfill庫給vw喇嘱、vh茉贡、vmin和vmax做適配的操作塞栅。

這是實現(xiàn)vw布局必不可少的一個插件者铜,因為少了這個插件,這將是一件痛苦的事情放椰。后面你就清楚作烟。

到此為止,有關(guān)于所需要的PostCSS已配置完砾医。并且簡單的介紹了各個插件的作用拿撩,至于詳細的文檔和使用,可以參閱對應插件的官方文檔如蚜。

vw兼容方案

在《再聊移動端頁面的適配》一文中压恒,詳細介紹了影暴,怎么使用vw來實現(xiàn)移動端的適配布局。這里不做詳細的介紹探赫。建議你花點時間閱讀這篇文章型宙。

先把未做兼容處理的示例二維碼貼一個:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市伦吠,隨后出現(xiàn)的幾起案子妆兑,更是在濱河造成了極大的恐慌,老刑警劉巖毛仪,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搁嗓,死亡現(xiàn)場離奇詭異,居然都是意外死亡箱靴,警方通過查閱死者的電腦和手機腺逛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衡怀,“玉大人屉来,你說我怎么就攤上這事”否” “怎么了茄靠?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝶桶。 經(jīng)常有香客問我慨绳,道長,這世上最難降的妖魔是什么真竖? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任脐雪,我火速辦了婚禮,結(jié)果婚禮上恢共,老公的妹妹穿的比我還像新娘战秋。我一直安慰自己,他們只是感情好讨韭,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布脂信。 她就那樣靜靜地躺著,像睡著了一般透硝。 火紅的嫁衣襯著肌膚如雪狰闪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天濒生,我揣著相機與錄音埋泵,去河邊找鬼。 笑死,一個胖子當著我的面吹牛丽声,可吹牛的內(nèi)容都是我干的礁蔗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼雁社,長吁一口氣:“原來是場噩夢啊……” “哼瘦麸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歧胁,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤滋饲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后喊巍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屠缭,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年崭参,在試婚紗的時候發(fā)現(xiàn)自己被綠了呵曹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡何暮,死狀恐怖奄喂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情海洼,我是刑警寧澤跨新,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站坏逢,受9級特大地震影響域帐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜是整,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一肖揣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浮入,春花似錦龙优、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挺庞。三九已至在跳,卻和暖如春颁井,著一層夾襖步出監(jiān)牢的瞬間憨琳,已是汗流浹背贡歧。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工闰靴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迎罗,地道東北人巢掺。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓句伶,卻偏偏與公主長得像劲蜻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子考余,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355