'當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?'

瀏覽器 CSS 設計 FLOW 開發指南 2019-09-09
"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

交叉軸對齊

Flex 項目還可以在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其他的要多,然後其他盒子像被通知了一樣伸展(stretch)到同樣的高度。這是 align-items 屬性初始值 stretch 在起作用:

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

交叉軸對齊

Flex 項目還可以在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其他的要多,然後其他盒子像被通知了一樣伸展(stretch)到同樣的高度。這是 align-items 屬性初始值 stretch 在起作用:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當你看見以 align- 前綴開頭的屬性時,說明它是控制 Flexbox 交叉軸上對齊的。align-items 操作交叉軸對齊,所有 Flex 項目在彈性線(flex line)內對齊。

除了 stretchalign-items 還可以取的值包括:

  • flex-start
  • flex-end
  • center
  • baseline

如果不想要盒子伸展到最高那個的高度,可以設置 align-items: flex-start。讓項目在交叉軸的起始邊緣對齊。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

交叉軸對齊

Flex 項目還可以在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其他的要多,然後其他盒子像被通知了一樣伸展(stretch)到同樣的高度。這是 align-items 屬性初始值 stretch 在起作用:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當你看見以 align- 前綴開頭的屬性時,說明它是控制 Flexbox 交叉軸上對齊的。align-items 操作交叉軸對齊,所有 Flex 項目在彈性線(flex line)內對齊。

除了 stretchalign-items 還可以取的值包括:

  • flex-start
  • flex-end
  • center
  • baseline

如果不想要盒子伸展到最高那個的高度,可以設置 align-items: flex-start。讓項目在交叉軸的起始邊緣對齊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

Flex 項目的初始值

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)。從頁面表現上看的話,就是內容較多的那個項目分配到的空間會比內容少的要多。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

交叉軸對齊

Flex 項目還可以在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其他的要多,然後其他盒子像被通知了一樣伸展(stretch)到同樣的高度。這是 align-items 屬性初始值 stretch 在起作用:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當你看見以 align- 前綴開頭的屬性時,說明它是控制 Flexbox 交叉軸上對齊的。align-items 操作交叉軸對齊,所有 Flex 項目在彈性線(flex line)內對齊。

除了 stretchalign-items 還可以取的值包括:

  • flex-start
  • flex-end
  • center
  • baseline

如果不想要盒子伸展到最高那個的高度,可以設置 align-items: flex-start。讓項目在交叉軸的起始邊緣對齊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

Flex 項目的初始值

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)。從頁面表現上看的話,就是內容較多的那個項目分配到的空間會比內容少的要多。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

這就是使用 Flexbox 帶來的靈活性、設置了 flex-basisauto,在沒有給項目設置額外大小限制的情況下愛,Flex 項目 有一個基礎尺寸(base sizemax-content。這個寬度是指項目中的內容在完全沒有折行的情況下的長度。然後每個項目會 在佔據的基礎尺寸的基礎上,按比例拿走一部分空間,這在 flexbox 規範中有詳情描述。

“注意: Flex shrink 因子分配負空間的時候,是在 Flex 項目的基礎尺寸的基礎之上增加的。最終分配的負空間多少,是根據因子值,按比例分配到每個項目頭上的。在大一點的項目 沒有顯著收縮之前,小的項目是不會收縮到零的。”

大一點的項目被抽取的空間相對(自身)來說是少的。你可以比較下面兩張圖,第一張圖裡每個項目 的內容量差不多,所以看起來差不多是一樣寬的。在第二張圖裡,第三項目的內容比較多,結果看到它分配到了更多的空間。

"

按我想法的話,CSS 網格佈局(grid)和彈性佈局(Flexbox)應該同時出現才對,這樣網頁佈局方案就變得完整了。事實是,彈性佈局先出現,因為使用彈性佈局創建類網格(grid-type)系統比使用浮動更加便捷,於是我們便得到了許多基於 Flexbox 的網格系統。實際上,Flexbox 的優勢並不是用來創建網格系統,這也是為什麼有時我們在用它創建網格系統時,感覺很費勁的原因。

我準備開一個小系列的文章,花點時間解密一下 Flexbox——就像過去我在講解 Grid 一樣。我們將看到 Flexbox 的設計目的,它真正做得好的地方,以及為什麼我們不選擇它作為佈局方法。本文中將會介紹當我們在使用 display: flex 的時候,到底發生了什麼?

Flex 容器

為了使用彈性佈局,我們需要先有一個元素充當 Flex 容器的角色。容器使用 display: flex 聲明:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

display: flex 到底做了什麼呢?在 Display Module Level 3 規範中,定義每 display 屬性值由兩部分組成:內部顯示模型(inner display model)和外部顯示模型(outer display model)。我們使用 display: flex 的時候,實際定義的是 display: block flexFlex 容器的外部顯示類型是 block,在文檔流(normal flow)中表現為塊級元素(block level element),內部顯示類型是 flex,所以容器的直接子元素將參與彈性佈局。

當然,我們還可以使用 display: inline-flex 定義 Flex 容器,與上面聲明類似,它實際定義的是 display: inline flexFlex 容器表現的像個行內元素,其直接子元素將參與彈性佈局。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

理解了元素的外部顯示模型和內部顯示模型,對理解元素及其子元素在頁面中的表現行為非常有幫助。你可以將這種思路帶入到任意其他類型的盒子中:這個元素的表現特徵為何?它的子元素呢?答案是跟外部顯示模型和內部顯示模型有關。

行與列

定義好 Flex 容器後,一些初始值就開始起作用了。在我們沒有設置任何其他屬性的情況下,所有的 Flex 項目 會排列為一行。之所以如此,是因為 flex-direction 的初始值是 row

flex-direction 屬性設置的是主軸(main axis)的方向,取值除了 row 之外,還包括:

  • column
  • row-reverse
  • column-reverse

這些排列在一行的 Flex 項目,始於內聯維度(inline dimension)的起始邊緣(start edge)、按照在源碼中出現的結構順序,依次排列。在規範中,這個“起始邊緣”被稱為 main-start

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的起始端

如果使用的是 column,則 Flex 項目從塊維度(block dimension)起始邊緣開始排列,從而形成一列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於塊維度的起始端

如果使用的是 row-reverse,則 main-startmain-end 的位置就調換了。因此,Flex 項目會一個個按照與之前相反的順序排列。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

main-start 位於內聯維度的終端

column-reverse 的作用於此類似。需要知道的是,這些值沒有“改變 Flex 項目的順序”,順序變了只是表徵而已,改變的其實是 Flex 項目從哪開始佈局,也就是說改變的是 main-start 的位置。因此,Flex 項目按照反序顯示,因為它們是沿著容器 的另一邊開始佈局的。

還有一個比較重要的點,就是 Flex 項目的排列順序上的不同只是純視覺上的。我們只是要求 Flex 項目從結束邊緣(end edge)開始顯示,對於屏幕閱讀器(screen reader)或是當你按 Tab 鍵切換元素的時候,結果順序還是在源碼中出現的順序。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

上面多此重複按下 Tab 鍵,可以觀察按鈕被 focus 的順序與在源碼中出現的順序一樣,與顯示順序無關。

Flexbox 中的兩根軸

我們已經講了彈性佈局裡一個非常重要的特性:主軸方向能從行切換到列。理解這種軸切換,能使我們更好地理解網格佈局中對齊的工作原理。網格屬於二維佈局,我們幾乎可以使用在彈性佈局中同樣的方式設置 Grid 項目在兩個軸上的對齊效果。

我們已經解釋了主軸,也就是 flex-direction 屬性值定義的那個方向。交差軸(cross axis)是另一個維度。如果你設置了 flex-direction: row,主軸是沿著行的,而交差軸沿著列向下。如果設置的是 flex-direction: column,則主軸沿著列向下,而交差軸則沿著行。這就是我們要介紹的彈性佈局的另一個重要特性,兩個軸的方向與屏幕的物理 維度沒有關係,我們沒有討論從左到右的行,或從上到下的列,是因為情況並非總是如此。

書寫模式

上面在講行和列的時候,提到了內聯和塊維度。本文使用英文書寫的,是水平書寫格式(譯註:原文是英文,不過現在中文書寫格式也與英文一樣)。也就是當你為 Flexbox 指定為 row 排列方式的話,會得到水平排列的 Flex 項目。這種情況下,main-start 在左邊——也就是英文句子開始的地方。

像在阿拉伯這樣的語言方向從右向左的國家,那麼起始邊緣始於右邊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當我只是創建了一個 Flex 容器的時候,Flexbox 的初始值表明 Flex 項目從右邊開始,向左排列顯示。內聯方向(inline direction)的起始邊緣就是我們使用的書寫模式下句子開始的地方。

垂直書寫模式(vertical writing mode)下的行是垂直的,因為在垂直語言環境下行就是垂直的,文本也是垂直顯示的。我們在 Flex 容器上設置 writing-mode: vertical-lr 就能看到效果。這時候,當你設置 flex-directionrow 的時候,就能看到在垂直方向上顯示的 Flex 項目。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

因此,行可以是水平顯示,main-start 在左邊或右邊,當然也可以是垂直的,main-start 在頂部。當你習慣於水平排列思維,看到垂直書寫模式下設置了 flex-direction: rowFlex 容器中的項目 是垂直排列的,可能感覺很奇怪,不過人家確實是在行的方向上排列的。

要讓 Flex 項目在塊維度上佈局的話,為 flex-direction 設置 columncolumn-reverse。在英語環境下,我們看見 Flex 項目從 Flex 容器頂部開始、依次往下佈局排列的。

在垂直書寫模式下,塊維度是橫跨頁面的,類似於此種模式下塊元素的排列方式。如果設置了 vertical-lr,則塊元素是從左到右排列的。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

但不論塊元素是在什麼方向顯示排列的,如果 flex-direction 設置 column 的話,那麼就是在塊維度上佈局的。

理解了行和列在不同的書寫模式中,表現在不同的物理方向上,對理解 GridFlexbox 中的一些術語非常有用。我們沒有在 GridFlexbox 中提到“從左到右”或是“從上到下”是因為我們沒有做任何文檔書寫模式的假設。我們現在的 CSS 正在變得更加兼容書寫模式,如果你想了解更多表現行為於此類似的其他屬性和值的話,可以閱讀我寫的文章 Logical Properties and Values(https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/)。

好了,我們來總結一下:

  • flex-direction: row
  • 主軸 = 內聯維度
  • main-start 位於在給定書寫模式下句子起始的地方
  • 交叉軸 = 塊維度
  • flex-direction: column
  • 主軸 = 塊維度
  • 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-starjustify-content 還可使用的值包括:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evently(在 Box Alignment 中添加)

這些值用於分配 Flex 容器可用空間(available space)。這是項目移動和間隔的原因。如果使用了 justify-content: space-between,可用空間在項目之間平均分配,當然了,前提是有空間可供分配。如果 Flex 容器空間過窄(所有項目 佈局完成後沒有額外的空間了),justify-content 就不起任何作用了。

我們可以設置 flex-directioncolumn 看下,此時 Flex 容器因為沒有設置 height ,所以不存在剩餘空間,justify-content: space-between 也不會起作用。如果你設置一個足夠高的 height,待所有項目 佈局好後,因為還有剩餘空間,就會看到效果。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

交叉軸對齊

Flex 項目還可以在只有一行的 Flex 容器上,執行交叉軸對齊。這種對齊控制的是盒子們在這跟線上的對齊方式。下例中,有一個盒子的內容比其他的要多,然後其他盒子像被通知了一樣伸展(stretch)到同樣的高度。這是 align-items 屬性初始值 stretch 在起作用:

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

當你看見以 align- 前綴開頭的屬性時,說明它是控制 Flexbox 交叉軸上對齊的。align-items 操作交叉軸對齊,所有 Flex 項目在彈性線(flex line)內對齊。

除了 stretchalign-items 還可以取的值包括:

  • flex-start
  • flex-end
  • center
  • baseline

如果不想要盒子伸展到最高那個的高度,可以設置 align-items: flex-start。讓項目在交叉軸的起始邊緣對齊。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

Flex 項目的初始值

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)。從頁面表現上看的話,就是內容較多的那個項目分配到的空間會比內容少的要多。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

這就是使用 Flexbox 帶來的靈活性、設置了 flex-basisauto,在沒有給項目設置額外大小限制的情況下愛,Flex 項目 有一個基礎尺寸(base sizemax-content。這個寬度是指項目中的內容在完全沒有折行的情況下的長度。然後每個項目會 在佔據的基礎尺寸的基礎上,按比例拿走一部分空間,這在 flexbox 規範中有詳情描述。

“注意: Flex shrink 因子分配負空間的時候,是在 Flex 項目的基礎尺寸的基礎之上增加的。最終分配的負空間多少,是根據因子值,按比例分配到每個項目頭上的。在大一點的項目 沒有顯著收縮之前,小的項目是不會收縮到零的。”

大一點的項目被抽取的空間相對(自身)來說是少的。你可以比較下面兩張圖,第一張圖裡每個項目 的內容量差不多,所以看起來差不多是一樣寬的。在第二張圖裡,第三項目的內容比較多,結果看到它分配到了更多的空間。

當我們在使用 display: flex 的時候,瀏覽器到底發生了什麼?

內容多的項目分配到了更多的空間

Flexbox 在我們沒有使用更多屬性的前提下,儘可能的提供給我們一個合理的佈局結果。與一刀切平均分配每個項目 一樣的寬度、導致可能出現有內容多項目被擠壓的非常高的情況不同的是,彈性佈局會給內容多的項目 分配更多的顯示空間。這種行為是彈性佈局最佳的使用場景。 彈性佈局最擅長於以一種靈活和內容感知的方式——沿著一個軸——放置一組項目。本文到此只是稍微接觸了一些皮毛,在本系列後面的文章中我會適當地講解這些算法。

總結

本文中,我們講解了彈性佈局中使用到的一些初始值,解釋了當我們聲明瞭 display: flex 的時候,實際發生了什麼。一路分析下來,發現東西還是很多的,文中涉及到幾個屬性牽涉到彈性佈局的許多關鍵特性。

彈性佈局如此靈活:默認情況下,它試圖對內容做出正確選擇——壓縮或拉伸 Flex 項目以獲得最佳的可讀性。彈性佈局還支持書寫模式(writing mode):行和列的方向與所使用的書寫模式相關。通過選擇空間的分佈方式,彈性佈局允許將 Flex 項目作為一個組在主軸上對齊;我們還可以在一個伸縮線(flex line)中對齊項目,在交叉軸上以彼此聯繫的方式移動 Flex 項目。重要的是,彈性佈局能感知 Flex 項目的內容大小,會嘗試在沒有設置其他額外屬性的情況下,來合理的分配空間給各個 項目。在以後的文章中,我們將更深入地討論這些知識點,並做進一步分析什麼時間以及為什麼去選擇使用彈性佈局。

版權

作者:zhangbao90s

鏈接:https://juejin.im/post/5d2da274f265da1bb003f242

著作權歸作者所有。

感謝閱讀

記得點擊右上角的關注喲,歡迎點贊轉發評論收藏喲。

關注我,每天一篇優質好文,陪你一起從入門到精通。

"

相關推薦

推薦中...