2017年如何在移動(dòng)端優(yōu)雅的使用flex
做過移動(dòng)端的同學(xué)都知道移動(dòng)端布局太難了,終端太多了,傳統(tǒng)的布局方式已經(jīng)力不從心,各種新的布局方式被發(fā)明
在flex之前,傳統(tǒng)布局有流式布局(就是默認(rèn)的方式),絕對(duì)定位布局,彈性布局(em),和浮動(dòng)布局,其中浮動(dòng)布局并不是為布局而設(shè)計(jì)的,使用起來略顯繁瑣
2009年,對(duì)前端來說是不平凡的一年,html5定稿,es5.1發(fā)布,flex應(yīng)運(yùn)而生,天生響應(yīng)式,生而為布局,使用及其簡單
但是理想很豐滿,現(xiàn)實(shí)很骨感,flex三改其規(guī)范,瀏覽器實(shí)現(xiàn)不一,各種神坑,本文將總結(jié)2017年移動(dòng)端使用flex的最佳實(shí)踐和經(jīng)驗(yàn)
兼容性
2017年9月份,現(xiàn)在來看下flex的兼容性,可以發(fā)現(xiàn)絕大部分都是綠色
上圖中紅色箭頭代表我們應(yīng)該兼容的瀏覽器情況,在國內(nèi),UC和QQ瀏覽器的份額不容忽視,上圖中的 1 2 3 其實(shí)代表flex的三版語法,flex有09年版語法,11年版語法和標(biāo)準(zhǔn)語法;右上角帶黃色小方塊的代表需要添加-webkit-前綴
將上圖總結(jié)一下,移動(dòng)端需要的兼容情況如下:
再來看一下百度給出的移動(dòng)設(shè)備的統(tǒng)計(jì)情況,分別是安卓和ios,可以發(fā)現(xiàn)現(xiàn)在需要兼容安卓4.1+,IOS7+,這里百度給出的數(shù)據(jù),當(dāng)然你應(yīng)該根據(jù)自己產(chǎn)品的統(tǒng)計(jì)情況來確定兼容情況
總結(jié)一下本文各處的最佳實(shí)踐,兼容性目標(biāo)是安卓4.1+,IOS7+,UC和qq瀏覽器
屬性對(duì)照
通過上面的目標(biāo)和caniuse,很容易得出我們需要寫09和標(biāo)準(zhǔn)兩版語法,只有在兩版語法中都存在屬性才能使用,下面給出兩版語法的對(duì)照關(guān)系,注意這不是語法指南,語法指南請(qǐng)看結(jié)尾處的推薦資料
容器的屬性
容器屬性包括:
- display
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
項(xiàng)目的屬性
項(xiàng)目屬性包括:
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
采坑經(jīng)驗(yàn)
一般來說只要09版語法有對(duì)應(yīng)功能,就可以使用了,但是移動(dòng)端還有一些坑,導(dǎo)致某些屬性不能用
justify-content: space-around 不能用,舊版語法沒有,但是可以用space-between+容器的padding模擬
flex-wrap: wrap 不能用,對(duì)應(yīng)的舊版語法 box-lines: mutiple 大部分瀏覽器不支持,也就是說不能折行
uc span行內(nèi)元素作為子項(xiàng)時(shí) display 必須設(shè)置為block,最好直接使用塊級(jí)元素
實(shí)戰(zhàn)
說了這么多下面給一份標(biāo)準(zhǔn)的寫法,一個(gè)flex屬性應(yīng)該這么寫
webkit前綴09版 webkit前綴標(biāo)準(zhǔn)版 標(biāo)準(zhǔn)版
舉個(gè)例子,display: flex要這么寫
display: -webkit-box; display: -webkit-flex; display: flex;
一定有同學(xué)說這也太麻煩了,有沒有啥簡單的辦法呢?還真有,共有三種辦法,感謝前輩
第一種,編輯器插件,有一個(gè)叫做autoprefix插件,sublime就可以安裝,你只需寫標(biāo)準(zhǔn)屬性,然后按一下快捷鍵就能夠自動(dòng)填充前綴屬性。這種方法用起來最簡單,但這種方法后面會(huì)不太好維護(hù),比如有一天不需要09版語法了怎么破???一個(gè)一個(gè)去改吧,o(╯□╰)o
第二種,預(yù)處理器mixin,如果你用過less或者sass的話,一定知道m(xù)ixin,下面已less 2.x為例,sass大同小異
.display-flex(@display: flex) { & when (@display=flex) { display: -webkit-box; } & when (@display=inline-flex) { display: -webkit-inline-box; } display: e("-webkit-@{display}"); display: @display; } .flex-direction(@direction) { & when (@direction=row) { -webkit-box-orient: horizontal; -webkit-box-direction: normal; } & when (@direction=row-reverse) { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; } & when (@direction=column) { -webkit-box-orient: vertical; -webkit-box-direction: normal; } & when (@direction=column-reverse) { -webkit-box-orient: vertical; -webkit-box-direction: reverse; } -webkit-flex-direction: @direction; flex-direction: @direction; } .flex-wrap(@wrap) { & when (@wrap=nowrap) { -webkit-box-lines: single; } & when (@wrap=wrap) { -webkit-box-lines: multiple; } -webkit-flex-wrap: @wrap; flex-wrap: @wrap; } .justify-content(@justify-content) { & when (@justify-content=flex-start) { -webkit-box-pack: start; } & when (@justify-content=flex-end) { -webkit-box-pack: end; } & when (@justify-content=center) { -webkit-box-pack: center; } & when (@justify-content=space-between) { -webkit-box-pack: justify; } -webkit-justify-content: @justify-content; justify-content: @justify-content; } .align-items(@align-items) { & when (@align-items=flex-start) { -webkit-box-align: start; } & when (@align-items=flex-end) { -webkit-box-align: end; } & when (@align-items=center) { -webkit-box-align: center; } & when (@align-items=baseline) { -webkit-box-align: baseline; } & when (@align-items=stretch) { -webkit-box-align: stretch; } -webkit-align-items: @align-items; align-items: @align-items; } .order(@order) { -webkit-box-ordinal-group: @order; -webkit-order: @order; order: @order; } .flex(@flex) { -webkit-box-flex: @flex; -webkit-flex: @flex; flex: @flex; }
在使用的只要一行就行了
.container { .display-flex; .flex-direction(row); .justify-content(center); }
上面的代碼less編譯完的結(jié)果如下
.container { display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -webkit-flex-direction: row; flex-direction: row; -webkit-box-pack: center; -webkit-justify-content: center; justify-content: center; }
有同學(xué)說這么麻煩,我不想寫啊?其實(shí)應(yīng)該有人已經(jīng)寫好了,比如compass,可以參考一下
這種方式的前提就是已經(jīng)使用了css預(yù)處理器,可維護(hù)性比第一種方法更好;但是以我的經(jīng)驗(yàn)來說,其實(shí)大部分項(xiàng)目的mixin未必是有人維護(hù)的,比如可能有一天不需要前綴版本了,但是并一定會(huì)有人去更新的
第三種,css后處理器,其實(shí)自從postcss出來之后,自動(dòng)加前綴的活就該交給postcss來做了,有了這個(gè)插件我們只需要配置要兼容的瀏覽器版本就可以了,加前綴的事情后處理器自動(dòng)幫你解決,最近babel也出了一個(gè)類似的babel-env
fis中可以使用fis-postprocessor-autoprefixer這個(gè)插件,我在之前的文章《經(jīng)驗(yàn)無線步驟頁改版總結(jié)》中有介紹
webpack中可以使用postcss-loader這個(gè)loader
終于可以和瀏覽器前綴愉快的玩耍了^_^
普及一個(gè)小科普知識(shí),css后面的實(shí)驗(yàn)室性不會(huì)再以加前綴的方式進(jìn)行了,而是會(huì)通過瀏覽器的設(shè)置方式來顯示開啟實(shí)驗(yàn)屬性,因?yàn)榍熬Y的方式不夠優(yōu)雅。。。這鍋主要還是怪前端開發(fā)者,因?yàn)槲覀儼?,只寫webkit前綴,都不寫標(biāo)準(zhǔn)屬性,o(╯□╰)o
總結(jié)
希望本文能夠幫助你更好的使用flex,少踩一些坑,現(xiàn)在在移動(dòng)端已經(jīng)可以任性的使用flex了,但pc端還不行,ie8。。。如果沒有兼容性問題,那就快來使用這一好用的布局方式吧
最后我強(qiáng)烈建議大家閱讀大漠老師的《圖解CSS3》,這是我見過講css3講的最好的書了