| 文章簡介:CSS Flexible盒模型3又簡稱為Flexbox。摒棄我們傳統上使用的一些hack和組件,Flexbox給網路的發展帶來了很多正能量和興奮濟,讓我們一起把複雜的網站布局變得簡易和快速。 |
簡介
CSS Flexible盒模型3又簡稱為Flexbox。摒棄我們傳統上使用的一些hack和組件,Flexbox給網路的發展帶來了很多正能量和興奮濟,讓我們一起把複雜的網站布局變得簡易和快速。早前在Flexbox: fast track to layout nirvana?一文中介紹了Flexbox的一些基礎知識。在本文中,我將更進一步,借用Modernizr指令碼庫使用不同的樣式做Flexbox在各瀏覽器下做一些差異化處理,為Flexbox在各瀏覽器下提供最佳展示水平。
推出案例
在這篇文章中建立的例子,看起來如下圖所示:
圖片最終布局樣本。
這個樣本包含了多個伸縮容器(flexbox container)。如果你願意,可以點擊樣本查看,閱讀或探索更詳細的代碼。
整體布局
樣本網站的基本布局是這樣的:
<section> <nav></nav> <article></article> <article></article> </section>
<section>設定為一個伸縮容器,代碼如下所示:
section { display: -ms-flexbox; -ms-box-orient: horizontal;/*IE10中顯不一行,類似於flex-direction:row功能*/ display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; }
註:從2011年到Opera和Chrome提供的最新規範,由於IE10目前支援不同的flexbox文法,在IE10中設定特定的屬性。Firefox和其他的webkit核心瀏覽器(如Safari)支援一個更舊版本的flexbox文法(2009),這使用flexbox更糟糕。除此之外,Modernizr報告IE10支援現代flexbox的文法,儘管它他還沒有用,因此我們需要使用老的文法來處理IE10下的flexbox效果,而不是使用Modernizr規則來做IE10的相容。詳細的可以看下文,你可以擷取更多的細節介紹。
讓他們都在同一水平流上,但<nav>使用下面的規則,迫使其在單獨的一行中顯示:
nav { padding: 1rem; -webkit-flex: 1 100%; -moz-flex: 1 100%; -ms-flex: 1 100%; flex: 1 100%; }
設定“flex-basis”為100%,使用其寬度和父容器的寬度一樣,同時迫使其他伸縮項目到新的一行。<article>的“flex-grow”的值設定如下:
article:nth-of-type(1) { -webkit-flex: 2; -moz-flex: 2; -ms-flex: 2; flex: 2; } article:nth-of-type(2) { -webkit-flex: 3; -moz-flex: 3; -ms-flex: 3; flex: 3; }
使他們在主軸點有一定比例的空間——第一個<article>佔40%,也就是寬度的五分之二;第二個<article>(也就是圖片容器)佔60%,也就是寬度的五分之三。這是值得記住——這個比例是只有在同一線上的伸縮項目具有,並非所有伸縮項目都具有的比例。
註:“flex-basis”是一個收縮基準值,首先用在伸縮項目上,在那之後主軸剩餘的空間會根據每個伸縮項目的“flex-grow”伸縮比率來劃分給每個伸縮項目,分配主軸的剩餘空間。當“flex-grow”沒有顯式的設定值時,它的預設值為“1”。為了更好的瞭解他是如何工作的原理,你可以閱讀flexbox模組中的flex部分,或者閱讀《Flexbox——快速布局神器》這篇文章裡面有關於flex的內容介紹。
伸縮項目
當你設定了一個元素為伸縮容器的時候,它只會影響他的子項目,而不會進一步的影響他的後代元素。但是沒有什麼可以阻止你為他們的後代設定為伸縮項目,使用一些布局變得複雜化。很簡單,在這裡,我把<nav>設定為伸縮容器,我可以讓他置中對齊,而且不必擔心容器的寬度或視窗的寬度大小。
nav { display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center;/*ie10水平置中*/ display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; /*水平置中*/ -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; }
接著再把<ul>設定為伸縮容器,保證他的子項目li能置中,代碼如下所示:
nav ul { text-align: center; display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center; display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; width: 80%; } nav a { width: 100%; }
我還添加了一些屬性來解決導覽功能表項的外觀。我希望<ul>不完全展開穿過螢幕,並且讓所有文本置中顯示,所以我設定了一個"width:80%"和"text-align:center"。同時給連結設定了寬度為100%,用來確保連結跨整個清單項目寬度。
接下來是神奇的時刻。在這一點上,清單項目看起來有眯重疊和奇怪,而用當他們開始封裝時看起來有點笨。沒有使用媒體查詢實現一個響應式的菜單,看上去很酷,那麼我們需要下面的代碼來實現:
nav ul li { margin: 0 1.5rem; -webkit-flex: auto; -moz-flex: auto; -ms-flex: auto; flex: auto; min-width: 5rem; }
在這裡,我給清單項目設定了一個margin,讓他們有一定的空間,給他們設定了一個min-width,並且將"flex"設定為“auto”。這是flex的一個特殊的值,可以讓伸縮項目具有一個min-width的值,當沒有多餘的空間的時候,讓伸縮項目保持一個常數大小(min-width),但有多餘的空間時,伸縮項目能擴大填補。當你擴充和收縮頁面的時候看看會發生什嗎?
接下來設定第二個<article>,並設定裡面每個段落(包括段落裡的img):
article:nth-of-type(2) { display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center; -ms-box-align: center; display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: inline-flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; -webkit-align-items: center; -moz-align-items: center; -ms-align-items: center; align-items: center; -webkit-align-content: flex-start; -moz-align-content: flex-start; -ms-align-content: flex-start; align-content: flex-start; } article p { margin: 0.5rem; -webkit-flex: 1 20rem; -moz-flex: 1 20rem; -ms-flex: 1 20rem; flex: 1 20rem; } article p img { display: block; width: 100%; border: 1px solid black; }
在這裡給他們設定了個固定的flex-basis值,所以他們會根據每行的數量增加和減少自己的寬度(如下圖所示,沒有使用媒體查詢),並且會使用每一項,和每一項裡面的內容水平垂直置中顯示。
一個沒有媒體查詢的響應式映像框。
Flexbox反饋
支援Flexbox的瀏覽器有Webkite核心瀏覽器、Presto-based Opera、Firefox(即將),要真正支援主流瀏覽器將還需要一段時間。這意味著,如果我們想使用flxbox還需要選擇一些備案方法。2009年開始一些瀏覽器(老的webkit、firefox)支援老版的Flexbox文法。奇怪的是IE10從2011後既支援老的文法又支援新的文法。值得慶幸的是Modernizr指令碼庫使用“flexbox”和“flexbox-legacy”標記能檢測出Flexbox的現代文法和Flexbox舊的文法。實際上它並不支援這兩種——它支援一個介於這兩者之間的一種文法。這就是為什麼我們一直在IE10中把代碼寫在CSS中,而不是使用Modernizr代碼塊,你將在後面的文章介紹中可以看到。
註:截至2013年04月會,已經有討論如何處理Modernizr中Flexbox在IE10中檢測問題。
下面的表總結了Flexbox最新文法和2009年、2011年等效的混合文法:
上表顯示了不同的flexbox文法支援跨不同的瀏覽器,對不同屬性的等價物。
註:從2009年的規範"box-lines"屬性看上去等同於“flex-wrap”,但不幸的是,這個並不支援混合文法的瀏覽器。
所以,我在樣本中添加了以下代碼,用來實現支援flexbox混合寫法,但不支援flexbox的瀏覽器的flebox效果:
.no-flexbox section { display: -webkit-box; display: -moz-box; -webkit-box-orient: horizontal; -moz-box-orient: horizontal; } .no-flexbox nav { padding: 1rem; width: 20%; } .no-flexbox article { -webkit-box-flex: 1; -moz-box-flex: 1; } .no-flexbox article p { float: left; } .no-flexbox article img { display: block; width: 200px; }
然後在樣式中加入不支援flexbox,甚至不支援混合flexbox文法瀏覽器的相容樣式代碼:
.no-flexbox-legacy nav, .no-flexbox-legacy article { float: left; } .no-flexbox-legacy nav { width: 20%; } .no-flexbox-legacy article { width: 36%; } .no-flexbox article img { float: left; }
註:一個用來產生跨瀏覽器的flexbox代碼,並且可以幫你瞭解不同瀏覽器使用文法的線上工具Flexy Boxes。
Flexbox線上產生工具
在70+ 優秀的前端工具中收錄了類似於Flexy Boxes線上產生Flexbox的其他工具:
- Flexplorer
- CSS Flexbox Please!
- Flexiejs
——大漠
添加簡單的媒體查詢實現寬屏和窄屏的布局
最後,為瞭解決寬屏和窄屏下的布局,我決定添加幾個媒體查詢。但注意怎麼在媒體查詢中添加這些代碼,因為Flexbox天生就是建立響應式布局的神器。
首先在支援混合文法上寫一些代碼來解決響應式效果:
@media all and (max-width: 600px) { h1 { font-size: 5rem; } .no-flexbox section { -webkit-box-orient: vertical; -moz-box-orient: vertical; } .no-flexbox nav { width: 100%; margin-left: -3rem; } .no-flexbox nav a, .no-flexbox nav ul, .no-flexbox nav li { width: 100%; } }
接下來,一個現代flexbox修複,沒有在所有的瀏覽器,在小螢幕寬度。
@media all and (max-width: 480px) { article:nth-of-type(1) { -webkit-flex: 1 100%; -moz-flex: 1 100%; -ms-flex: 1 100%; flex: 1 100%; } body { min-width: 320px; } nav ul { width: 100%; } .no-flexbox-legacy nav, .no-flexbox-legacy article { float: none; } .no-flexbox-legacy nav, .no-flexbox-legacy article { width: 100%; } }
最後用媒體查詢給大多少螢幕情況下設定一個置中效果:
@media all and (min-width: 1100px) { section { width: 1100px; margin: 0 auto; } }
總結
此時是有限度的使用Flexbox,當都使用同一種方式支援現代瀏覽器的時候,Flexbox才會變得更加簡易。到現在為止,更有效果的支援,只是一些簡單的效果,單行的可以用flexbox,對於多行的在混合文法中就無法得到瀏覽器的支援。因為它的標準,我的樣本啟動並執行很正常,儘管混合文法的flexbox不如現代flexbox布局。另一個有趣的問題是,Firefox好像不支援置中,後來只好使用"margin: 0 auto"來實現(safari下支援置中)。
對於flexbox的一些簡單的使用,在現代瀏覽器(Chrome、Firefox、Safari、Opera Presto 12.1+,IE10+,IOS和Android)可以得到很好的支援。
譯者手語:整個翻譯依照原文線路進行,並在翻譯過程略加了個人對技術的理解。如果翻譯有不對之處,還煩請同行朋友指點。謝謝!
如需轉載煩請註明出處:
英文原文:http://dev.opera.com/articles/view/advanced-cross-browser-flexbox