前言
露珠最近研究了一下flex的布局方式,發現項w3c推出的這套布局解決方案對於日益復雜的前端開發布局來說是確實是一利器,並且在不同的屏幕上實現了真正的響應式布局:不再單純地依賴百分比和float的強拼硬湊來達到設計需求,在各個屏幕上顯示效果友好,彈性的伸縮元素,簡潔易維護的代碼。只可惜,這位老兄有一位致命的缺點----除了chrome外幾乎所有手機上瀏覽器都沒有兼容它!!,或者支持程度大不一樣!這樣開發人員頭疼的問題就來了,剛剛在手機上忽略掉IE這個強盜的兼容問題,又來一個?!。flex的優勢那么多,但是如果瀏覽器不兼容的話也是沒法子用的。很多人會選擇放棄它。在最初面對這樣的問題的時候我是拒絕的,他們說要加兼容特技,我說我不用,還是absoute布局爽。但是!duang一下,露珠懷着人不學不知義的想法,想到google旗下產品(chrome、安卓等)在前端界的地位,相信不久各大瀏覽器廠商都會像標准靠齊。所以flex是要學習的,不過在這之前我們可以用替代方案解決它。本篇文章將對新(felx)舊(flex-box)兩種布局方式對比。由於網上關於flex布局方式的介紹已經很多,本文不會對flex做詳細介紹,主要分享一下用舊方式(box)解決flex移動端的兼容問題。首先我們寫一個flex的例子,展示一下他的部分屬性。
一個小示例
手機端一張卡片列表,高度100像素,全屏寬,左邊圓角圖片(box1),中間三行介紹,上中下均分卡片高度,中間(box2)自適應分配剩余長度,最右邊按鈕(box3)。我們分別用幾個盒子代表定位的元素來簡單實現該需求。HTML結構的代碼如下:
<div class="box"> <div class="box1">red</div> <div class="box2"> <div class="item1">green</div> <div class="item2">blue</div> <div class="item3">gray</div> </div> <div class="box3">orange</div> </div>
實現效果大概是下面那樣的:
普通定位的實現
思路大概是這樣的:由於要實現中間的盒子box2長度適應拉伸,百分比是不可以做到的。所以采用box1和box3絕對定位,box2不設置寬度,分別設置左邊距(box1的寬度+box1到外框的寬度+box1到box2的間距)和右邊距(box3寬度+box3到外框的寬度+box3到box2的間距);由於三個box都需要垂直居中,所以為最外面的box設置一個百分比padding,即使如此也很難再外框高度拉伸的時候讓所有元素垂直居中。況且每個盒子的高度是固定(不是按照百分比)的而且是不一樣的。所以這樣的方式只能只有盡可能的接近效果,前提是外框高度不變情況下。如果需要垂直居中,可以用table布局,但是,諸位並不像因為一個這樣的居中屬性而去改變整個塊的布局方式吧?至於里面的三塊子盒子,則是按照外邊距來平均分布在box2中,下面是大概的偽代碼,不全列出來:
.box { position: relative;/*外框定位*/ padding: x% 0; } .box1 { position: absolute; left: 10px; } .box2 { padding-left: box1.width + box1.left + box2.margin-left;/*box2的左內邊距*/ padding-right: box3.width + box3.right + box2.margin-right;/*box的右邊距*/ } .box2.div{ margin-bottom: x%;/*box2內的元素排列*/ } .box3 { position: absolute;/*外框定位*/ right: 10px;/*外框定位*/ }
用普通的方式最難解決的是高度適應的問題,也就是在高度固定時元素垂直居中的問題。其次是中間元素剩余空間的分配。這還只是個很簡單的例子,如果遇上更加復雜的布局,要兼容調整的就不只一點代碼能解決了。
flex布局解決方案:
felx采用的是彈性布局,在聲明一個元素的display屬性為flex的時候,瀏覽器在元素內計算兩天軸來,兩條方向軸根據flex-direction屬性的值決定是縱軸位主軸還是橫軸為主軸。在這里,我們給box 設置felx屬性,並且將其X軸設置為主軸。然后讓里面的元素在副軸上(Y軸縱軸)上居中。為了設置box2分配剩余空間,我們給box2的flex屬性設置為auto:意思是擴大和縮放都在box2上。然后我們將box2的display屬性也設置為flex,為了均勻排列里面的元素,可以將box2的主軸設置為Y軸,然后再Y軸上設置均分屬性:justify-content: space-between;我們看下偽代碼:
.box { display: flex;/*申明布局方式*/ flex-direction:row;/*聲明主軸的方向*/ justify-content:flex-start;/*主軸的排列*/ align-items:center;/*副軸排列*/ } .box2 { flex-direction: column; justify-content: space-between; align-items: flex-start; flex: auto;/*自適應填充方式*/ }
簡簡單單幾行代碼,實現了普通布局花了2倍的代碼量完成的需求。而且不管高度寬度如何變化,里面的元素排列一直整整齊齊。當然在復雜的布局中省掉的不僅僅使代碼量,而且還有維護成本等一系列的開銷。這就是flex的優勢所在。但是致命缺陷馬上就要暴露,在手機端查看,卻出現了另一個鬼樣子(完全錯亂的排列順序)。這讓露珠很失望很失望。欣喜若狂的趕腳馬上煙消雲散。下面我們就要尋找兼容的解決的方案。
兼容版本box布局
據露珠所知,box布局方式是flex的前輩了,屬於老一代的解決方案。在w3c里面已經列為了標准。也就是說只要加上前綴,它就能被各個瀏覽器支持。下面我們就用此方法兼容一下手機瀏覽器。
.box{ display: -webkit-box;/*布局方式 相當於display:flex*/ -webkit-box-align: center;/*box的對齊方式 align-items:center;*/ } .box2{ display: -webkit-box; -webkit-box-orient: vertical;/*排列方式flex-direction: column*/ -webkit-box-pack: justify;/*box2的縱向排列方式 justify-content: space-between;*/ -webkit-box-flex:1; /*box2的伸縮比例 flex:auto;*/ }
以上代碼就是老舊版本的兼容寫法,雖然說它老,但是卻被各種瀏覽器兼容。通過測試,在chrome、安卓、ios上樣式和排列都是正常的。到此為止,我們做的小小的兼容示例就完成了!
小結
這是目前露珠在使用flex上遇到的一些兼容問題和解決的方案。實際上在實施過程中遇到的情況比此處更復雜。露珠也借助了flex學習了一下box布局,發現box布局早已有之,在國外已經被普遍使用,而吾等竟全然不知。每念及此,無不垂足頓胸,蹲守頓足啊。同時,希望露珠這篇文章能激發你學習新布局技術的動力。在前端這條路上,即使原地不動也算是退步。