1. 程式人生 > >2017年如何在移動端優雅的使用flex

2017年如何在移動端優雅的使用flex

作者:yanhaijing

做過移動端的同學都知道移動端佈局太難了,終端太多了,傳統的佈局方式已經力不從心,各種新的佈局方式被髮明

在flex之前,傳統佈局有流式佈局(就是預設的方式),絕對定位佈局,彈性佈局(em),和浮動佈局,其中浮動佈局並不是為佈局而設計的,使用起來略顯繁瑣

2009年,對前端來說是不平凡的一年,html5定稿,es5.1釋出,flex應運而生,天生響應式,生而為佈局,使用及其簡單

但是理想很豐滿,現實很骨感,flex三改其規範,瀏覽器實現不一,各種神坑,本文將總結2017年移動端使用flex的最佳實踐和經驗

相容性

2017年9月份,現在來看下flex的相容性,可以發現絕大部分都是綠色

上圖中紅色箭頭代表我們應該相容的瀏覽器情況,在國內,UC和QQ瀏覽器的份額不容忽視,上圖中的 1 2 3 其實代表flex的三版語法,flex有09年版語法,11年版語法和標準語法;右上角帶黃色小方塊的代表需要新增-webkit-字首

將上圖總結一下,移動端需要的相容情況如下:

安卓 2.1-4.3 4.4-∞ UC 11.4 QQ 1.2-∞
語法版本 09版 標準 09版 標準
是否字首
iOS Safari 3.2-6.1 7.1-8.4 9.2–∞
語法版本 09版 標準 標準
是否字首

再來看一下百度給出的移動裝置的

統計情況,分別是安卓和ios,可以發現現在需要相容安卓4.1+,IOS7+,這裡百度給出的資料,當然你應該根據自己產品的統計情況來確定相容情況

總結一下本文各處的最佳實踐,相容性目標是安卓4.1+,IOS7+,UC和qq瀏覽器

屬性對照

通過上面的目標和caniuse,很容易得出我們需要寫09和標準兩版語法,只有在兩版語法中都存在屬性才能使用,下面給出兩版語法的對照關係,注意這不是語法指南,語法指南請看結尾處的推薦資料

容器的屬性

容器屬性包括:

  • display

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

display

標準版 09版
display: flex display: box
display: inline-flex display: inline-box

flex-direction

標準版 09版
flex-direction: row box-orient: horizontal; box-direction: normal
flex-direction: row-reverse box-orient: horizontal; box-direction: reverse
flex-direction: column box-orient: vertical; box-direction: normal
flex-direction: column-reverse box-orient: vertical; box-direction: reverse

flex-wrap

標準版 09版
flex-wrap: nowrap box-lines: single
flex-wrap: wrap box-lines: multiple
flex-wrap: wrap-reverse

flex-flow是flex-direction和flex-wrap兩個屬性的簡寫,09版無對應屬性,09版可以分開寫兩條屬性

justify-content

標準版 09版
justify-content: flex-start box-pack: start
justify-content: flex-end box-pack: end
justify-content: center box-pack: center
justify-content: space-between box-pack: justify
justify-content: space-around

align-items

標準版 09版
align-items: flex-start box-align: start
align-items: flex-end box-align: end
align-items: center box-align: center
align-items: baseline box-align: baseline
align-items: stretch box-align: stretch

align-content,09版無對應屬性

專案的屬性

專案屬性包括:

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

order

標準版 09版
order: number box-ordinal-group: number

flex-grow,09版無對應屬性

flex-shrink,09版無對應屬性

flex-basis,09版無對應屬性

flex,標準版的flex是一個複合屬性,09版的box-flex僅支援配置數字

標準版 09版
flex: flex-grow flex-shrink flex-basis box-flex: number

align-self,09版無對應屬性

09版的語法對flex專案的可配置功能非常弱,僅能調整順序和伸縮性

採坑經驗

一般來說只要09版語法有對應功能,就可以使用了,但是移動端還有一些坑,導致某些屬性不能用

justify-content: space-around 不能用,舊版語法沒有,但是可以用space-between+容器的padding模擬

flex-wrap: wrap 不能用,對應的舊版語法 box-lines: mutiple 大部分瀏覽器不支援,也就是說不能折行

uc span行內元素作為子項時 display 必須設定為block,最好直接使用塊級元素

實戰

說了這麼多下面給一份標準的寫法,一個flex屬性應該這麼寫

webkit字首09版
webkit字首標準版
標準版

舉個例子,display: flex要這麼寫

display: -webkit-box;
display: -webkit-flex;
display: flex;

一定有同學說這也太麻煩了,有沒有啥簡單的辦法呢?還真有,共有三種辦法,感謝前輩

第一種,編輯器外掛,有一個叫做autoprefix外掛,sublime就可以安裝,你只需寫標準屬性,然後按一下快捷鍵就能夠自動填充字首屬性。這種方法用起來最簡單,但這種方法後面會不太好維護,比如有一天不需要09版語法了怎麼破???一個一個去改吧,o(╯□╰)o

第二種,前處理器mixin,如果你用過less或者sass的話,一定知道mixin,下面已less 2.x為例,sass大同小異

.display-flex(@display: flex) {
    & when (@display =flex) {
        display: -webkit-box;
    }
    & when (@display =inline-flex) {
        display: -webkit-inline-box;
    }
    display: e("[email protected]{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 (@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 =baseline) {
        -webkit-box-pack: baseline;
    }
    & when (@justify-content =stretch) {
        -webkit-box-pack: 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編譯完的結果如下

.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;
}

有同學說這麼麻煩,我不想寫啊?其實應該有人已經寫好了,比如compass,可以參考一下

這種方式的前提就是已經使用了css前處理器,可維護性比第一種方法更好;但是以我的經驗來說,其實大部分專案的mixin未必是有人維護的,比如可能有一天不需要字首版本了,但是並一定會有人去更新的

第三種,css後處理器,其實自從postcss出來之後,自動加字首的活就該交給postcss來做了,有了這個外掛我們只需要配置要相容的瀏覽器版本就可以了,加字首的事情後處理器自動幫你解決,最近babel也出了一個類似的babel-env

fis中可以使用fis-postprocessor-autoprefixer這個外掛,我在之前的文章《經驗無線步驟頁改版總結》中有介紹

終於可以和瀏覽器字首愉快的玩耍了^_^

普及一個小科普知識,css後面的實驗室性不會再以加字首的方式進行了,而是會通過瀏覽器的設定方式來顯示開啟實驗屬性,因為字首的方式不夠優雅。。。這鍋主要還是怪前端開發者,因為我們啊,只寫webkit字首,都不寫標準屬性,o(╯□╰)o

總結

希望本文能夠幫助你更好的使用flex,少踩一些坑,現在在移動端已經可以任性的使用flex了,但pc端還不行,ie8。。。如果沒有相容性問題,那就快來使用這一好用的佈局方式吧