原文:What Happens When You Create A Flexbox Flex Container?,by Rachel Andrewcss
按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現纔對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,由於使用彈性佈局建立類網格(grid-type)系統比使用浮動更加便捷,因而咱們便獲得了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優點並非用來建立網格系統,這也是爲何有時咱們在用它建立網格系統時,感受很費勁的緣由。算法
我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 同樣。咱們將看到 Flexbox 的設計目的,它真正作得好的地方,以及爲何咱們不選擇它做爲佈局方法。本文中將會介紹當咱們在使用 display: flex
的時候,到底發生了什麼?app
爲了使用彈性佈局,咱們須要先有一個元素充當 Flex 容器的角色。容器使用 display: flex
聲明:ide
📷See the Pen Smashing Flexbox Series 1: display: flex; by Rachel Andrew佈局
display: flex
到底作了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。咱們使用 display: flex
的時候,實際定義的是 display: block flex
。Flex 容器的外部顯示類型是 block
,在文檔流(normal flow)中表現爲塊級元素(block level element),內部顯示類型是 flex
,因此容器的直接子元素將參與彈性佈局。flex
固然,咱們還可使用 display: inline-flex
定義 Flex 容器,與上面聲明相似,它實際定義的是 display: inline flex
。Flex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。ui
📷See the Pen Smashing Flexbox Series 1: display: inline-flex; by Rachel Andrewflexbox
理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行爲很是有幫助。你能夠將這種思路帶入到任意其餘類型的盒子中:這個元素的表現特徵爲什麼?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。spa
定義好 Flex 容器後,一些初始值就開始起做用了。在咱們沒有設置任何其餘屬性的狀況下,全部的 Flex 項目 會排列爲一行。之因此如此,是由於 flex-direction
的初始值是 row
。設計
flex-direction
屬性設置的是主軸(main axis)的方向,取值除了 row
以外,還包括:
column
row-reverse
column-reverse
這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個「起始邊緣」被稱爲 main-start
:
main-start
位於內聯維度的起始端
若是使用的是 column
,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而造成一列。
main-start
位於塊維度的起始端
若是使用的是 row-reverse
,則 main-start
和 main-end
的位置就調換了。所以,Flex 項目會一個個按照與以前相反的順序排列。
main-start
位於內聯維度的終端
column-reverse
的做用於此相似。須要知道的是,這些值沒有「改變 Flex 項目的順序」,順序變了只是表徵而已,改變的實際上是 Flex 項目從哪開始佈局,也就是說改變的是 main-start
的位置。所以,Flex 項目按照反序顯示,由於它們是沿着容器 的另外一邊開始佈局的。
還有一個比較重要的點,就是 Flex 項目的排列順序上的不一樣只是純視覺上的。咱們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序仍是在源碼中出現的順序。
上面多此重複按下 Tab 鍵,能夠觀察按鈕被 focus 的順序與在源碼中出現的順序同樣,與顯示順序無關。
咱們已經講了彈性佈局裏一個很是重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使咱們更好地理解網格佈局中對齊的工做原理。網格屬於二維佈局,咱們幾乎可使用在彈性佈局中一樣的方式設置 Grid 項目在兩個軸上的對齊效果。
咱們已經解釋了主軸,也就是 flex-direction
屬性值定義的那個方向。交差軸(cross axis)是另外一個維度。若是你設置了 flex-direction: row
,主軸是沿着行的,而交差軸沿着列向下。若是設置的是 flex-direction: column
,則主軸沿着列向下,而交差軸則沿着行。這就是咱們要介紹的彈性佈局的另外一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,咱們沒有討論從左到右的行,或從上到下的列,是由於狀況並不是老是如此。
上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過如今中文書寫格式也與英文同樣)。也就是當你爲 Flexbox 指定爲 row
排列方式的話,會獲得水平排列的 Flex 項目。這種狀況下,main-start
在左邊——也就是英文句子開始的地方。
像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。
See the Pen Smashing Smashing Flexbox Series 1: row with rtl text by Rachel Andrew
當我只是建立了一個 Flex 容器的時候,Flexbox 的初始值代表 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是咱們使用的書寫模式下句子開始的地方。
垂直書寫模式(vertical writing mode)下的行是垂直的,由於在垂直語言環境下行就是垂直的,文本也是垂直顯示的。咱們在 Flex 容器上設置 writing-mode: vertical-lr
就能看到效果。這時候,當你設置 flex-direction
爲 row
的時候,就能看到在垂直方向上顯示的 Flex 項目。
See the Pen Smashing Smashing Flexbox Series 1: row with a vertical writing mode by Rachel Andrew
所以,行能夠是水平顯示,main-start
在左邊或右邊,固然也能夠是垂直的,main-start
在頂部。當你習慣於水平排列思惟,看到垂直書寫模式下設置了 flex-direction: row
的 Flex 容器中的項目 是垂直排列的,可能感受很奇怪,不過人家確實是在行的方向上排列的。
要讓 Flex 項目在塊維度上佈局的話,爲 flex-direction
設置 column
或 column-reverse
。在英語環境下,咱們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。
在垂直書寫模式下,塊維度是橫跨頁面的,相似於此種模式下塊元素的排列方式。若是設置了 vertical-lr
,則塊元素是從左到右排列的。
See the Pen Smashing Smashing Flexbox Series 1: column in vertical-lr writing mode by Rachel Andrew
但不論塊元素是在什麼方向顯示排列的,若是 flex-direction
設置 column
的話,那麼就是在塊維度上佈局的。
理解了行和列在不一樣的書寫模式中,表如今不一樣的物理方向上,對理解 Grid 和 Flexbox 中的一些術語很是有用。咱們沒有在 Grid 和 Flexbox 中提到「從左到右」或是「從上到下」是由於咱們沒有作任何文檔書寫模式的假設。咱們如今的 CSS 正在變得更加兼容書寫模式,若是你想了解更多表現行爲於此相似的其餘屬性和值的話,能夠閱讀我寫的文章Logical Properties and Values。
好了,咱們來總結一下:
main-start
位於在給定書寫模式下句子起始的地方main-start
位於給定書寫模式下塊元起始佈局的地方使用 display: flex
後,還會有其餘一些事情發生。在這個系列的以後的文章裏,我會好好講解一下對齊。本文中,咱們先來看下使用 display: flex
後,使用的一些默認值。
注意: 對齊屬性最開始起源於 Flexbox 規範。但正如 Flexbox 規範中解釋的那樣,Box Alignment 規範最終將取代 Flexbox 規範中定義的這些屬性。
justify-content
的初始值是 flex-start
,就像咱們在 CSS 中這樣聲明瞭:
.container {
display: flex;
justify-content: flex-start;
}
複製代碼
這就是爲何 Flex 項目是從容器的起始邊緣開始排列的緣由。而 row-reverse
則是調換了起始邊緣與結束邊緣,結束邊緣變爲主軸開始的地方。
當你看見以 justify-
前綴開頭的屬性時,說明它是控制 Flexbox 主軸上對齊的。justify-content
操做主軸對齊,全部 Flex 項目在開始處對齊。
除了 flex-star
,justify-content
還可以使用的值包括:
flex-end
center
space-around
space-between
space-evently
(在 Box Alignment 中添加)這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的緣由。若是使用了 justify-content: space-between
,可用空間在項目之間平均分配,固然了,前提是有空間可供分配。若是 Flex 容器空間過窄(全部項目 佈局完成後沒有額外的空間了),justify-content
就不起任何做用了。
咱們能夠設置 flex-direction
爲 column
看下,此時 Flex 容器由於沒有設置 height
,因此不存在剩餘空間,justify-content: space-between
也不會起做用。若是你設置一個足夠高的 height
,待全部項目 佈局好後,由於還有剩餘空間,就會看到效果。
See the Pen Smashing Flexbox Series 1: column with a height by Rachel Andrew
Flex 項目還能夠在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其餘的要多,而後其餘盒子像被通知了同樣伸展(stretch)到一樣的高度。這是 align-items
屬性初始值 stretch
在起做用:
See the Pen Smashing Guide to Layout: clearfix by Rachel Andrew
當你看見以 align-
前綴開頭的屬性時,說明它是控制 Flexbox 交叉軸上對齊的。align-items
操做交叉軸對齊,全部 Flex 項目在彈性線(flex line)內對齊。
除了 stretch
,align-items
還能夠取的值包括:
flex-start
flex-end
center
baseline
若是不想要盒子伸展到最高那個的高度,能夠設置 align-items: flex-start
。讓項目在交叉軸的起始邊緣對齊。
See the Pen Smashing Flexbox Series 1: align-items: flex-start by Rachel Andrew
Flex 項目是有初始設置的,以下:
flex-grow: 0
flex-shrink: 1
flex-basis: auto
就是說項目默認不會擴展(grow)來填充主軸上的可用空間。若是給 flex-grow
設置了一個正值,那麼項目就會擴展剩餘的空間。
項目的 flex-shrink
屬性處置值爲正值 1,表示能收縮(shrink)。也就是說,當 Flex 容器比較窄的時候,在沒有任何溢出發生的狀況下,項目會變得儘量小。這是一個明智的行爲,通常來講,咱們但願盒子裏的內容不要溢出。
爲了默認可以獲得很好地佈局,flex-basis
初始值使用了 auto
。我會在之後的系列文章中解釋這個屬性的行爲。你能夠暫時把它認爲是「大小剛恰好」(big enough to fit the content)。從頁面表現上看的話,就是內容較多的那個項目分配到的空間會比內容少的要多。
See the Pen Smashing Flexbox Series 1: initial values of flex items by Rachel Andrew
這就是使用 Flexbox 帶來的靈活性、設置了 flex-basis
爲 auto
,在沒有給項目設置額外大小限制的狀況下愛,Flex 項目 有一個基礎尺寸(base size)max-content
。這個寬度是指項目中的內容在徹底沒有折行的狀況下的長度。而後每一個項目會 在佔據的基礎尺寸的基礎上,按比例拿走一部分空間,這在 flexbox 規範中有詳情描述。
「注意: Flex shrink 因子分配負空間的時候,是在 Flex 項目的基礎尺寸的基礎之上增長的。最終分配的負空間多少,是根據因子值,按比例分配到每一個項目頭上的。在大一點的項目 沒有顯著收縮以前,小的項目是不會收縮到零的。」
大一點的項目被抽取的空間相對(自身)來講是少的。你能夠比較下面兩張圖,第一張圖裏每一個項目 的內容量差很少,因此看起來差很少是同樣寬的。在第二張圖裏,第三項目的內容比較多,結果看到它分配到了更多的空間。
內容多的項目分配到了更多的空間
Flexbox 在咱們沒有使用更多屬性的前提下,儘量的提供給咱們一個合理的佈局結果。與一刀切平均分配每一個項目 同樣的寬度、致使可能出現有內容多項目被擠壓的很是高的狀況不一樣的是,彈性佈局會給內容多的項目 分配更多的顯示空間。這種行爲是彈性佈局最佳的使用場景。 彈性佈局最擅長於以一種靈活和內容感知的方式——沿着一個軸——放置一組項目。本文到此只是稍微接觸了一些皮毛,在本系列後面的文章中我會適當地講解這些算法。
本文中,咱們講解了彈性佈局中使用到的一些初始值,解釋了當咱們聲明瞭 display: flex
的時候,實際發生了什麼。一路分析下來,發現東西仍是不少的,文中涉及到幾個屬性牽涉到彈性佈局的許多關鍵特性。
彈性佈局如此靈活:默認狀況下,它試圖對內容作出正確選擇——壓縮或拉伸 Flex 項目以得到最佳的可讀性。彈性佈局還支持書寫模式(writing mode):行和列的方向與所使用的書寫模式相關。經過選擇空間的分佈方式,彈性佈局容許將 Flex 項目做爲一個組在主軸上對齊;咱們還能夠在一個伸縮線(flex line)中對齊項目,在交叉軸上以彼此聯繫的方式移動 Flex 項目。重要的是,彈性佈局能感知 Flex 項目的內容大小,會嘗試在沒有設置其餘額外屬性的狀況下,來合理的分配空間給各個 項目。在之後的文章中,咱們將更深刻地討論這些知識點,並作進一步分析什麼時間以及爲何去選擇使用彈性佈局。
(完)