相信研究過CSS3的同學對Flexbox布局一定不會陌生(作為一個未來主流的布局方式,至少有所耳聞)。最近完成了兩個項目:一個是移動端H5 項目,一個是嵌入Html頁面的Mac客戶端項目。為了慶祝這兩個項目不用再兼容萬惡的IE,同時要體現出現代浏覽器的優勢,決定在項目中嘗試使用 Flexbox布局。項目第一個版本完成後回過頭來看,還是有不少需要注意的地方。現將項目中的一些經驗總結一下,希望能夠對想嘗試使用Flexbox的 同學有所幫助,在恰當的地方使用恰當的布局方法。
Flexbox布局俗稱伸縮布局,它可以簡單快速的創建一個具有彈性功能的布局。一個Flexbox布局是由一個伸縮容器(flex containers)和在這個容器裡的伸縮項目(flex items)組成。伸縮容器(flex containers)是一個Html標簽元素,並且“display”屬性顯式的設置了“flex”屬性值。在伸縮容器中的所有子元素都會自動變成伸縮 項目(flex items)。當在一個小屏幕上顯示的時候,Flexbox可以讓元素在容器(伸縮容器)中進行自由擴展和收縮,從而容易調整整個布局。
Flexbox布局能夠讓我們很輕松的實現以下效果:
這些效果是不是很誘人,為了我們都能更好的理解接下來的內容,需要對Flexbox有一個初步的認識。沒有了解過Flexbox知識的同學請先移步伸縮布局--打開布局天堂之門!
如果已經對Flex有了初步了解,那讓我們來舉例說明什麼時候更適合使用該布局。
【No.1】youku H5播放頁的控制區域
將浏覽器的UA改為iOS或者android,然後訪問youku的播放頁。先來看下示意圖:
播放區域分為四個部分:mod-one為播放按鈕區域,mod-two為時間顯示區域,mod-three為切換視頻質量和其他操作區域,mod-four為全屏按鈕區域。
該播放區域的排版需求如下:mod-one和mod-two定寬依次居左,mod-four定寬居右,mod-three自動填充剩余的寬度且該區域內的元素依次居右排列(除了切換視頻質量按鈕外還有其他操作按鈕)。
下面來看看youku如何使用Flexbox進行Html布局以及CSS實現:
x-controls為Flexbox伸縮容器,核心樣式如下:
display: -webkit-box; display: -moz-box; display: box; -webkit-box-orient: horizontal; -moz-box-orient: horizontal; box-orIEnt: horizontal;
該CSS設置了x-controls為Flexbox容器,子元素(伸縮項目)橫向排列。box-pack沒有設置,默認為start,即彈性盒模型對象的子元素從開始位置對齊。
PS:使用Flexbox布局的時候盡量使用兼容語法,避免使用最新語法導致舊版系統(android2.2,iOS5)出現不兼容的情況。
如果要兼容Windows Phone(IE10+)需要加入IE專有語法(IE和其他浏覽器語法稍有區別,一定要注意),詳見最後附上的兼容代碼。
回到youku播放頁,x-play-control為播放按鈕區域,根據需求只需要設置寬度即可。x-time-display為時間顯示區域,CSS設置同播放按鈕區域。
x-settings需要設置自動填充屏幕剩余寬度,同時該模塊內的子元素需要居右顯示,因此它既要作為一個伸縮項目,又要作為一個伸縮容器。CSS代碼如下:
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orIEnt: horizontal;
-moz-box-orIEnt: horizontal;
box-orIEnt: horizontal;
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
x-settings code
為了結構的合理性,youku將x-fullscreen放到了x-settings中,因此需要絕對定位到最右側。否則可以將x-fullscreen作為兄弟節點放到x-settings後,同樣也能實現該效果。
【NO.2】UC網址導航
某天使用UC浏覽器的網址導航,下意識的查看了一下源碼,發現其導航部分也使用了Flexbox布局。心裡暗喜,這也算是為推進CSS3在國內的普及做出了一點貢獻。
直接用浏覽器訪問該網址,示意圖如下:
該需求比較簡單,8個標簽兩兩一組。4組平均分配屏幕寬度。
Html結構及樣式如下:
block為伸縮容器,設置如下樣式:
display: -webkit-box; -webkit-box-pack: justify;
block-list為伸縮項目,設置如下樣式:
-webkit-box-flex: 1; width: 25%;
簡單的幾句css就實現了自動伸縮的布局。當然,這個例子比較簡單,使用CSS2的技術也可以實現,比如block-list中的width: 25%; 我想就是起了優雅降級的作用。
先讓我們看一個需求:
同樣是一個播放器的操作區域,分為三部分:左邊為視頻質量選擇按鈕,居左顯示;中間為控制視頻進度的按鈕組,居中顯示;右邊為分享和全屏按鈕,居右顯示。
了解需求後我很興奮,剛剛學習的Flexbox布局終於有用武之地了。不管三七二十一便為這版UI制定了兩套方案:
兩套方案Html結構相同,如圖:
CSS方案略有不同,方案一:
不給伸縮項目定寬,直接使用box-pack:justify將3個伸縮項目定位到圖中的位置,代碼:
display: -webkit-box; display: -ms-flexbox; display: box; -webkit-box-pack: justify; -ms-flex-pack: justify; box-pack: justify; -webkit-box-orient: horizontal; -ms-box-orient: horizontal; box-orIEnt: horizontal; fbJustify
不用給伸縮項目寫任何CSS即可實現UI中的效果,完成後感慨Flexbox簡直是逆天的存在!
方案二:
給三個伸縮項目div設置-webkit-box-flex:1; 然後分別給第一個設置text-align: left; 第二個設置text-align: center; 第三個設置text-align: right; 可以通過CSS3的:first-child和:last-child完成。
某天,前端開發的過程中,產品跑來對我說:分享按鈕這期先不上。so easy,我直接使用display: none隱藏了分享對應的 a 標簽。
然後……相信已經有同學發現會出現神馬狀況了。
我去,中間的按鈕往右移動了。不論使用方案一還是方案二都會出現此問題。通過分析後發現,在方案一中,由於我伸縮項目的寬度都是根據其內容撐開的。 所以右側子內容不見了,伸縮項目的寬度自然也就發生了變化,重新分配三個伸縮項目後就是圖中的效果。而方案二雖然設置了伸縮比flex:1; 但是總體寬度還是和容器的內容有關系。後來仔細想想,雖然這次歪打正著提前遇到了問題,但就算分享功能按期上線,並不是所有視頻都提供分享,因此最終還是 會出現這個問題。
如何解決呢?
對於這種包含居中顯示的布局(且需求可能隨時會變化),最好的方法是左右兩個伸縮項目定寬。中間的伸縮項目設置flex:1,具有固定寬度的伸縮項 目不會對彈性的伸縮項目產生影響。這個例子告訴我們,在了解需求的基礎上,盡量將布局做的通用性強一點,能夠適應更多的突發情況。CSS近幾年一直推崇的 OOCSS理念即如此。
最後說一個Flexbox實現的水平、垂直居中例子:
伸縮容器設置如下樣式,伸縮項目無論是否定義寬高都可實現水平、垂直居中效果。
Html代碼:<div class="flexbox"><div>這裡可以放任何元素</div></div>
/* 舊版語法 */ display: -webkit-box; display: -ms-flexbox; -webkit-box-pack: center; -ms-flex-pack: center; -webkit-box-align: center; -ms-flex-align: center; /* 新版語法 */ display: -webkit-flex; display: flex; -webkit-align-item: center; align-item: center; -webkit-justify-content: center; justify-content: center; Flexbox居中
附上一段Flexbox新老版本兼容及對應語法的代碼,供大家參考。
/* display */ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10+ */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ /* 沿著主軸方向對齊項目 */ -webkit-box-pack: start; -moz-box-pack: start; -webkit-justify-content: flex-start; -ms-flex-pack: start; justify-content: flex-start; /* 沿著側軸方向對齊項目 */ -webkit-box-align: start; -moz-box-align: start; -webkit-align-item: flex-start; -ms-flex-align: start; align-item: flex-start; /* 伸縮項排列方式 */ -webkit-box-direction: normal; /* 舊版伸縮項對齊方式,在新版中已經合並到了flex-direction */ -moz-box-direction: normal; -webkit-box-orient: horizontal; -moz-box-orIEnt: horizontal; /* vertical */ -webkit-flex-direction: row; /* column, row-reverse, column-reverse */ -ms-flex-direction: row; flex-direction: row; /* 伸縮項目是否換行 */ -webkit-flex-wrap: nowrap; -ms-flex-wrap: nowrap; flex-wrap: nowrap; /* 多行伸縮容器的對齊 */ -webkit-align-content: stretch; -ms-flex-line-pack: stretch; align-content: stretch; /* 改變伸縮項布局順序和使伸縮項目可適應伸縮容器 */ -webkit-box-ordinal-group: 1; -moz-box-ordinal-group: 1; -ms-flex-order: 1; -webkit-order: 1; order: 1; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; Flexbox兼容
本篇文章目的是起到拋磚引玉的作用,幫助大家能夠更快的將Flexbox布局運用到自己的項目中。我相信CSS未來發展的方向就是采用Flexbox這種布局方式。