簡書的Markdown貌似不支持插入iframe,所以文章里的JSFiddle示例都改做截圖了漏益,如果有需要可以點擊下面的鏈接,到眾成查看深胳,英文版鏈接一并附上绰疤。
譯者:kangflict(飛揚)
鏈接:http://www.zcfy.cc/article/966
原文:https://bocoup.com/weblog/dive-into-flexbox
簡介
Flexbox 是 CSS3 中提出的新布局模型,用于適應現(xiàn)代網(wǎng)絡開發(fā)中日益復雜的布局需求稠屠。 近來峦睡,F(xiàn)lexbox 的語法逐漸穩(wěn)定下來,本文來為大家揭開它的神秘面紗权埠,并盤點其技術細節(jié)榨了。瀏覽器支持將會快速增長,因此當對 Flexbox 的支持足夠廣泛以至達到實用水平時攘蔽,你將會在這場游戲當中拔得頭籌龙屉。如果想要了解它的工作方式和原理,那么就繼續(xù)讀下去吧满俗!
為什么需要 Flexbox转捕?
長期以來,人們使用 table唆垃、float五芝、inline-block 以及其他 CSS 特性來對站點內容進行布局。然而辕万,這些工具沒有一個是為當前的復雜網(wǎng)頁或網(wǎng)絡應用設計的枢步。像垂直居中這樣的簡單的需求都需要費點兒力氣才能滿足,以至于我們通常認為單槍匹馬實現(xiàn)靈活柵格布局這樣的需求不太現(xiàn)實渐尿,因此各種 CSS 柵格布局框架獲得了巨大的成功醉途。
規(guī)范進展與瀏覽器支持
Flexbox 規(guī)范的相關工作已經(jīng)進行 3 年之久,很多瀏覽器廠商都發(fā)布了其實驗性質的實現(xiàn)砖茸。2012 年 9 月隘擎,針對 Flexbox 語法的第三次主要修訂進入了 W3C 的候選推薦階段。這說明 W3C 對當前的語法是滿意的凉夯,并鼓勵瀏覽器廠商進行實現(xiàn)货葬。
Flexbox 規(guī)范大事年表:
- 2009 年 7 月,工作草案(display: box;)
- 2011 年 3 月劲够,工作草案(display: flexbox;)
- 2011 年 11 月宝惰,工作草案(display: flexbox;)
- 2012 年 3 月,工作草案(display: flexbox;)
- 2012 年 6 月再沧,工作草案(display: flex;)
- 2012 年 9 月,候選推薦(display: flexe;)
各個瀏覽器都在積極地接納 Flexbox尊残。本文寫就之時炒瘸,Chrome 22+淤堵、Opera 12.1+ 以及 Opera Mobile 12.1+ 均已支持 Flexbox。Firefox 18 和 Blackberry 10 也將馬上跟進顷扩。我建議使用支持 Flexbox 的瀏覽器來閱讀本文拐邪,以便觀察示例如何工作。
相關概念和術語
盡管在 Flexbox 的幫助下隘截,以前千辛萬苦才能實現(xiàn)或者根本不敢想象的布局都能輕而易舉地實現(xiàn)扎阶,但要真正習慣以 Flexbox 的方式進行布局還是需要一定的時間。在使用 Flexbox 時婶芭,新的術語或概念都可能成為攔路虎东臀,因此我們先來討論一下術語和概念的問題。
Flexbox 布局涉及 Flex 容器(Flex Container)和 Flex 項目(Flex Item)犀农。Flex 容器的 display
屬性為 flex
或 flexbox
惰赋。flex
屬性使得容器渲染為塊級元素,而 inline-flex
則使其渲染為行內元素呵哨。
下面是聲明 Flex 容器的示例:
.flex-container {
display: -webkit-flex;
display: flex;
}
本文中的所有代碼示例都將包含全面的瀏覽器廠商前綴赁濒。
Flex 容器的任何子元素都是 Flex 項目,并且 Flex 項目可以有任意多個孟害。Flex 容器之外的任何元素以及 Flex 項目內的元素都將照常渲染拒炎。簡而言之,F(xiàn)lex 容器決定 Flex 項目在其內部的布局方式挨务。
Flex 布局線(Flex Line)
在Flex容器內击你,F(xiàn)lex 項目沿 Flex 布局線 排布。默認情況下耘子,每個容器只有一條 Flex 布局線果漾。
上圖的示例展示了默認情況下兩個項目在容器中的排布:從左到右,沿水平 Flex 布局線排列谷誓。
書寫模式(Writing Modes)
使用 Flexbox 進行富有創(chuàng)造性的布局不可避免地要改變 Flex 布局線的方向绒障。默認情況下,F(xiàn)lex 布局線與文本書寫方向一致:從左到右捍歪,從上到下户辱。
W3C 有一個工作草案,是關于一項稱作書寫模式(Writing Modes)的新特性的糙臼。書寫模式為從右至左或縱向的文字排布提供了新的實現(xiàn)方式庐镐,在對特定的語言進行排版時常會遇到這樣的需求。
書寫模式仍然處于半成品狀態(tài)变逃,不過 direction
屬性已經(jīng)在 Chrome 中得到了支持必逆。上面的示例中,如果如果我們將 direction
的值設置為 rtl
(從右到左),那么不光文本內容會從右往左渲染名眉,F(xiàn)lex 布局線的方向也會改變粟矿,從而影響頁面的布局。
這或許就是很多與 Flexbox 相關的術語非常抽象的原因损拢。如果不能確定頁面語言的話陌粹,我們就不能簡單地用“上”“下”“左”“右”來代表布局方向。
主軸與側軸(Main Axis and the Cross Axis)
Flexbox 通過引入概念主軸(Main Axis)和側軸(Cross Axis)來體現(xiàn)對書寫模式的支持福压。Flex 布局線與主軸的方向一致掏秩,而側軸則與主軸正交。
每條軸的起點荆姆、終點以及方向的名字如下所示:
- 主軸起點(Main Start)
- 主軸終點(Main End)
- 主軸方向(Main Direction蒙幻,有時也稱作流方向,即 Flow Direction)
- 側軸起點(Cross Start)
- 側軸終點(Cross End)
- 側軸方向 (Cross Direction)
主軸和側軸兩個術語非常重要胞枕,我們有必要在繼續(xù)之前將其徹底搞懂杆煞。在使用 Flexbox 進行布局的時候,任何東西都與此有關腐泻。本文所有的示例中决乎,書寫模式都是從左往右從上往下的,但是我們必須了解并不一定所有情況下都是如此派桩。
Flex 容器之屬性
flex-direction
flex-direction
能夠改變 Flex 容器的軸向构诚。flex-direction
的默認值為 row
,即按照 writing-mode
的方向對 Flex 項目進行排布铆惑,默認情況下從左到右范嘱,從上往下。其他可能的值如下:
- row-reverse:主軸起點和終點對換员魏。如果書寫模式(writing-mode)從左往右丑蛤,那么此時 Flex 項目會由右往左進行排布;
- column:主軸與側軸對換撕阎。如果書寫系統(tǒng)為水平方向的受裹,那么 Flex 項目將沿縱向排布;
- column-reverse:與column的效果相同虏束,只是軸向翻轉棉饶。
將前面示例中的 flex-direction
值改為 column
。
現(xiàn)在镇匀,F(xiàn)lex 項目變?yōu)榭v向排列的了照藻。
justify-content
Flex 容器的 justify-content
屬性用于控制 Flex 項目在主軸上的位置『骨郑可能的值有:
- flex-start(默認值)
- flex-end
- center
- space-between
- space-around
將 justify-content
的值設置為 center
能夠讓 Flex 項目沿主軸居中:
flex-start
幸缕、flex-end
以及 center
的含義相當直截群发,但是 space-between
和 space-around
這兩個用于確定 Flex 項目間留白的屬性值的含義就不那么明顯了。下面這張來自規(guī)范的示意圖對各個屬性值做出了最佳詮釋:
align-items
align-items
是對 justify-content
的補充发乔,它確定的是 Flex 項目在側軸上的位置也物。可能的取值有:
- flex-start(默認值)
- flex-end
- center
- baseline
- stretch
我們將 align-items
的值設置為 center
列疗,從而讓 Flex 項目在側軸居中排布:
flex-start
、flex-end
和 center
的含義仍舊直截了當浪蹂,strech
也相當簡單:讓 Flex 項目充滿從側軸起點到側軸終點的所有空間抵栈。baseline
則使得 Flex 項目沿基線對齊±ご危基線是由 Flex 項目的內容計算得出的古劲。下面出自 Flexbox 規(guī)范的示意圖對此做出了最佳闡釋:
flex-wrap
到現(xiàn)在為止,每個 Flex 容器都只有一條 Flex 布局線缰猴,利用 flex-wrap
屬性产艾,就可以得到有多條 Flex 布局線的的容器。flex-wrap
可選的值如下:
- nowrap(默認值)
- wrap
- wrap-reverse
如果 flex-wrap
的值為 wrap
滑绒,那么當一條 Flex 布局線無法容納所有 Flex 項目時闷堡,多余的項目就會折轉到附加的 Flex 布局線上。新添的 Flex 布局線沿側軸的方向排列疑故。
這里有一個使用 flex-wrap
的示例:
wrap-reverse
的效果與 wrap
相同杠览,只是 Flex 布局線將沿與側軸相反的方向添加。
align-content
align-content
能夠影響 flex-wrap
的行為纵势。它與 align-items
類似踱阿,但是并不是用于對齊 Flex 項目,而是用于對齊 Flex 布局線钦铁。正如你所想软舌,它們可能的取值也非常相似:
- stretch(默認值)
- flex-start
- flex-end
- center
- space-between
- space-around
這些值的效果與它們在 align-items
中的表親基本相同。
這里牛曹,我們將 align-content
設為 center
:
flex-flow
flex-flow
是 flex-direction
和 flex-wrap
的簡寫:
flex-flow: [flex-direction] [flex-wrap]
例如:
gistfile1.css
.flex-container {
-webkit-flex-flow: column nowrap;
flex-flow: column nowrap;
}
Flex 項目之屬性
Flex 項目是 Flex 容器的直接子元素佛点,F(xiàn)lex 容器中的文字段落也會被當做 Flex 項目處理。
Flex 項目的內容則會照常渲染躏仇。例如恋脚,float
屬性對 Flex 項目不起作用,但是 Flex 項目內部卻可以存在浮動元素焰手。
我們稱 Flex 項目有主軸尺寸和側軸尺寸糟描。主軸尺寸是 Flex 項目在主軸方向上的尺寸,側軸尺寸則是 Flex 項目在側軸方向上的尺寸书妻。事實上船响,通常 Flex 項目的寬和高分別就是它的主軸尺寸和側軸尺寸躬拢,不過這取決于 Flex 容器的軸的設置。
下面的屬性能夠影響 Flex 項目的行為见间。
order
order
最為簡單聊闯,它控制著 Flex 項目的渲染順序。本例中米诉,我們將一個 Flex 項目的 order
屬性設置為 -1
菱蔬,從而使其顯示在所有其他元素之前。
這對可訪問性來說可能非常有用史侣,因為有時我們需要文檔結構和頁面展示以不同的順序出現(xiàn)拴泌。
margin
你或許已經(jīng)對 margin: auto;
在通常情況下的效果非常熟悉了。在 Flexbox 的世界里惊橱,它仍然發(fā)揮著相似的作用蚪腐,只不過更加的強大∷捌樱“自動”邊距能夠吸收掉多余的空白回季,從而將 Flex 項目推到不同的位置上去。
這里正林,我們?yōu)榈谝粋€ Flex 項目設定 margin-right: auto;
泡一,從而使得該項目右邊所有多余的空白都被吸收掉:
接著,我們使用 margin: auto;
來摘取 CSS 排版的圣杯:真正的垂直居中卓囚!
align-self
Flex 項目的 align-self
屬性能夠覆蓋 Flex 容器為其指定的 align-items
屬性瘾杭。兩個屬性具有相同的取值范圍:
- stretch(默認)
- flex-start
- flex-end
- center
- baseline
此例中,我們?yōu)槊總€ Flex 項目指定了不同的 align-self
值:
上例中有兩個 Flex 項目的 align-items
值為 baseline
哪亿,這是因為 baseline
項目是以彼此為參照來進行對齊的粥烁。
flex
終于到 Flexbox 中的 flex
屬性了。flex
確定了 Flex 項目在主軸剩余空間排布時的策略蝇棉。
讓我們來逐一過目 flex
的常見取值:
flex: [數(shù)字]
該語法通過指定一個數(shù)字讨阻,來確定當前 Flex 項目占主軸剩余空間的比例。
本例中篡殷,第一個 Flex 項目占剩余空間的 2/4钝吮,其余兩個 Flex 項目各占 1/4:
將每個項目的 flex
屬性都設置為 1 是一項非常有用的技巧,此時主軸剩余空間將被平均分配給各個 Flex 項目板辽。
flex: initial
flex
屬性為 initial
的項目將會失去彈性伸縮能力奇瘦,但是在必要的時候仍然能夠縮小(被擠芯⑾摇)耳标。
flex: auto
flex
屬性為 auto
的項目擁有在主軸上進行彈性伸縮的所有能力。
目前邑跪,Opera 12.11 能夠支持 auto
次坡,但是 Chrome 23.0.1271.95 還不可以呼猪。實際上,我們只需要使用 flex: 1
就可以繞過這個問題砸琅。
flex: none
flex
屬性為 none
的項目在任何情況下都不具備彈性伸縮的能力宋距。
flex 進階
事實上,flex
是 flex-grow
症脂、flex-shrink
和 flex-basis
的簡寫:
flex: [flex-grow] [flex-shrink] [flex-basis]
不過谚赎,多數(shù)情況下我們都不需要這樣寫,它需要對 flex 背后的算法更為精深的理解诱篷。如果你覺得自己是真正的猛士沸版,看這里的規(guī)范。
我們也可以為 flex-grow
兴蒸、flew-shrink
以及 flex-basis
分別指定屬性值。但是我強烈建議你不要這樣做细办,因為當使用 flex
簡寫形式時橙凳,瀏覽器會為沒有值的屬性指定更有意義的默認值。
visibility
如果有實現(xiàn)支持的話笑撞,對于 Flex 項目岛啸,visibility: collapse;
應當表現(xiàn)得與 visibility: hidden;
和 display: none;
不同。具有該屬性的 Flex 項目將會影響所在 Flex 容器的側軸尺寸茴肥,但是并不占據(jù)主軸方向的空間义起,也不可見裁替。這對動態(tài)添加移除 Flex 項目非常有用,同時也不影響 Flex 容器的側軸尺寸。
目前诱渤,visibility: collapse;
貌似在任何瀏覽器上都沒有得到正確的支持。當前的實現(xiàn)中拘荡,visibility: collapse;
的行為看上去與 visibility: hidden;
相同勿锅。我期待這種情況趕緊得以改觀。
這里有一個還不錯的 collapse
模擬實現(xiàn)皆警,能夠讓你看到規(guī)范中 collapse
是如何工作的拦宣。
總結
如你所見,F(xiàn)lexbox 是一種強大的新式布局工具信姓,將從根本上變革我們現(xiàn)有的網(wǎng)站布局手段鸵隧。亦如所見,它需要我們使用全新的思考方式來進行布局意推。我希望這篇文章能夠在你開始使用 Flexbox 對網(wǎng)站進行布局時幫你一把豆瘫。不知道你信不信,反正我是看到了光明的未來左痢。