Flexbox

CSS Podcast - 010: Flexbox

在回應式設計中,設計模式可能會很棘手,是一種內嵌於部分內容的側欄。對於可視區域空間而言,這個模式十分實用,但如果發生空間壓縮的情況,這種固定版面配置可能就會造成問題。

彈性 Box 版面配置模型 (flexbox) 是專為單維內容設計的版面配置模型。擅長擷取多種大小不一的項目,並為這些項目傳回最佳版面配置。

對於此側欄模式,這是理想的版面配置模型。Flexbox 不僅能協助將側欄和以內嵌方式顯示內容,當空間不足時,側欄也會分行。使用 Flexbox 時,您可以改為提供彈性的邊界,以提示內容的顯示方式,而不需要設定瀏覽器遵循的彈性尺寸。

Flex 版面配置提供哪些功能?

Flex 版面配置提供下列功能,您可在本指南中探索。

  • 它們可以以資料列或資料欄的形式顯示。
  • 這些規則遵循文件的撰寫模式。
  • 根據預設,這些是單行,但可能要求換行。
  • 版面配置中的項目可透過視覺方式重新排序,與 DOM 中的順序相反。
  • 空間可以在項目中分配,以便依據父項的可用空間而放大和縮小。
  • 您可以使用 Box Alignment 屬性,在項目周圍分配空間和彈性線。
  • 項目本身可以對齊跨軸。

主軸和交叉軸

瞭解 Flexbox 的關鍵在於瞭解主軸和交叉軸的概念。主軸是由 flex-direction 屬性設定的。如果為 row,您的主要軸會沿著資料列顯示,如果為 column,則主要軸位於欄上。

三個相鄰的方塊,旁邊有一個箭頭指向右。箭頭標有主軸

Flex 項目會一個在主軸上移動。請記住:我們能處理諸多事項,試圖為小組打造出最完善的版面配置。

交叉軸則是從另一個方向指向主軸,因此如果 flex-directionrow,則交叉軸會沿著資料欄執行。

三個不同高度的方塊,旁邊都有一個箭頭,指向左。箭頭標有主軸。另一個箭頭往上走。上到標有十字記號

您可以執行兩項操作。 您可以個別移動項目,也可以一次移動項目,讓這些項目會彼此對齊及彈性容器。此外,如果您有包裝的彈性行,您可以將這些行視為群組,控制這些行所指派空間的方式。您將會瞭解這在本指南中實際的運作方式。現在請注意,主軸遵循 flex-direction

建立 Flex 容器

我們可以瞭解 Flexbox 如何透過 Flexbox 執行一組不同大小的項目,以及使用 Flexbox 放置這些項目。

<div class="container" id="container">
  <div>One</div>
  <div>Item two</div>
  <div>The item we will refer to as three</div>
</div>

如要使用 Flexbox,您必須宣告要使用 Flex 格式結構定義,而非一般區塊和內嵌版面配置。方法是將 display 屬性的值變更為 flex

.container {
  display: flex;
}

如同版面配置指南所述,這將為您提供含有 Flex 子項的區塊層級方塊。Flex 項目使用其初始值後,會立即開始呈現一些 Flexbox 行為。

初始值表示:

  • 項目會以列的方式顯示。
  • 這些元件不會自動換行。
  • 不會為了填滿容器而擴充。
  • 這些都排在容器的開頭。

控制項目方向

即使您尚未新增 flex-direction 屬性,這些項目仍顯示為一列,因為 flex-direction 的初始值為 row。 如需一列,就不需要加入屬性。 如要變更方向,請新增屬性和下列四個值的其中之一:

  • row:項目會以資料列的形式排列。
  • row-reverse: 項目會以一列的方式,從 Flex 容器結尾的方向排列。
  • column:項目會以資料欄的形式配置。
  • column-reverse:項目會以資料欄形式,從 Flex 容器結尾的結尾。

您可以透過下方示範的一組項目來體驗所有值。

反向操作項目和無障礙功能

使用任何屬性重新排序視覺顯示時,請務必小心,避免改變 HTML 文件中的內容排序方式,以免對無障礙功能造成負面影響。row-reversecolumn-reverse 值就是很好的範例。系統只會依照視覺順序進行重新排序,而不會對邏輯順序進行。這點很重要,因為邏輯順序是螢幕閱讀器讀出內容的順序,所有使用鍵盤導覽的使用者都會遵循。

請觀看以下影片,您可以瞭解在反向列版面配置中,由於鍵盤導覽是遵循 DOM 而非視覺顯示,因此連結之間的分頁會中斷連線。

任何可以變更 Flexbox 或格線中項目順序的元件,都可能造成這個問題。因此,任何重新排序都應進行全面測試,確保網站不會對部分使用者使用網站造成困難。

如需詳細資訊,請參閱:

書寫模式與方向

根據預設,Flex 項目會排成一列。資料列會按照書寫模式和指令碼方向的語句流動。也就是說,如果你使用阿拉伯文,且文字方向為由右至左 (rtl) 行,則項目會排在右邊。定位點順序也會從右側開始,因為這是阿拉伯語句子的閱讀方式。

如果您使用垂直書寫模式 (例如某些日文字體),則系統會從上到下垂直執行一列。在這個示範中,請嘗試變更使用垂直書寫模式的 flex-direction

因此,Flex 項目的預設行為會連結至文件的寫作模式。大部分的教學課程都是以英文或其他水平方向編寫,由左至右書寫模式。如此一來,即可輕鬆假設彈性委刊項會在左側,並水平執行。

由於我們探討的是主軸和交叉軸,再加上寫出模式,我們所說的,在 Flexbox 中提到的「start」和「end」,不比頂端、底部、左側和右側,可能更容易理解。每個軸都有開頭和結尾。主軸的開頭稱為「main-start」。因此我們的彈性委刊項一開始會從主啟動。該軸的結尾為「main-end」。交叉軸的開頭為交叉開始,結束交叉點

上方字詞的標籤圖表

包裝 Flex 項目

flex-wrap 屬性的初始值為 nowrap。這表示如果容器空間不足,項目就會溢位。

一個包含九個項目的彈性容器,已縮小,行上有一個字詞,但空間不足以並排顯示這些項目,因此 Flex 項目已延伸至容器方塊外。
達到內容大小下限的彈性項目後,就會開始溢位容器

使用初始值顯示的項目會盡可能縮小,直到溢位到 min-content 的大小為止。

如要使項目包裝,請將 flex-wrap: wrap 新增至 Flex 容器。

.container {
  display: flex;
  flex-wrap: wrap;
}

當 Flex 容器封裝時,會建立多個彈性線。就空間分配而言,每一行都像是一個新的彈性容器。因此,如果您要包裝資料列,就無法在第 2 列中與第 1 列上方的內容對齊。這是一個 Flexbox 的意思。您可以控制單一軸、資料列或資料欄的對齊方式,而不能同時控制兩者的對齊方式,就像在格線中一樣。

Flex-flow

您可以使用簡寫 flex-flow 設定 flex-directionflex-wrap 屬性。舉例來說,如要將 flex-direction 設為 column,並允許項目包裝:

.container {
  display: flex;
  flex-flow: column wrap;
}

控制 Flex 項目中的空間

假設我們的容器空間比顯示項目所需的空間多,委刊項會在一開始時顯示,且不會依照空間填滿。不再因內容大小上限而繼續成長。 這是因為 flex- 屬性的初始值如下:

  • flex-grow: 0:未成長項目。
  • flex-shrink: 1:項目可能會小於其 flex-basis
  • flex-basis: auto:項目的基本大小為 auto

您可以用 flex: initial 的關鍵字值表示。flex 簡寫屬性或 flex-growflex-shrinkflex-basis 的長句會套用至 Flex 容器的子項。

為了提高項目大小,同時允許大型項目比小型項目擁有更多空間,請使用 flex:auto。您可以透過上方的示範嘗試操作。這會將屬性設為:

  • flex-grow: 1:項目大小可以大於 flex-basis
  • flex-shrink: 1:項目可以縮小小於其 flex-basis
  • flex-basis: auto:項目的基本大小為 auto

使用 flex: auto 意味著項目最終大小不同,因為每個項目在配置「最大內容大小」後,項目之間共用的空間會共用。因此,大型項目會有更多空間。 如要強制所有項目的大小一致,並忽略內容大小,請在示範中將 flex:auto 變更為 flex: 1

這個套件可解壓縮至:

  • flex-grow: 1:項目大小可以大於 flex-basis
  • flex-shrink: 1:項目可以縮小小於其 flex-basis
  • flex-basis: 0:項目的基本大小為 0

使用 flex: 1 表示所有項目的大小為零,因此 Flex 容器中的所有空間都可以發布。由於所有項目的 flex-grow 係數都是 1,因此這些項目的空間均等長,且空間共享同等。

讓商品以不同的速率成長

您不必為所有項目提供 1flex-grow 因子。您可以為彈性項目提供不同的 flex-grow 因素。在下方的示範中,第一個項目有 flex: 1、第二個 flex: 2 和第三個 flex: 3。 這些項目從 0 增加時,Flex 容器中的可用空間就會與六個共用。一個部分會給第一個項目 兩個部分到第二部分,第三部分則給第三部分

您可以在 autoflex-basis 中執行相同操作,但您需要指定三個值。第一個值是 flex-grow、第二個 flex-shrink 和第三個 flex-basis

.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

這種情況較不常見,因為使用 autoflex-basis 可讓瀏覽器瞭解空間分佈情形。如果您想讓項目成長幅度比演算法決定多一些,但或許會有幫助。

重新排序 Flex 項目

您可以使用 order 屬性重新排序 Flex 容器中的項目。這個屬性可按照一般群組中的項目順序排列。 項目會按照 flex-direction 指定的方向排列,最低值優先。如果多個項目擁有相同值,系統會與其他項目一起顯示。

以下範例會示範這個排序方式。

隨堂測驗

測試您對 Flexbox 的相關知識

flex-direction 預設為

row
根據預設,Flexbox 可將項目排入一列,並在起始時以線框排列項目。開啟換行功能後,系統會繼續建立用於流動子項的資料列。
column
將彈性方向設為資料欄是堆疊元素的絕佳方式,但這不是預設值。

根據預設,Flex 容器會納入子項。

true
必須啟用換行功能。
false
使用 flex-wrap: wrapdisplay: flex 納入子項

一個彈性的子項項目變形了,哪個彈性屬性有助於減輕這個問題?

flex-grow
這個屬性會說明元素是否可超出基礎大小,而非以特定基礎為基礎。
flex-shrink
是,這個屬性說明如何在寬度低於基準時處理大小調整。
flex-basis
這樣就能著手調整尺寸,但無法在寬度低於基準的情況下處理大小調整作業,例如在寬鬆的情況中處理。

Flexbox 對齊方式總覽

Flexbox 內建了一組屬性,可用於對齊項目以及在不同項目之間分配空間。這些屬性非常實用,現已移至各自的規格中,您也會在格狀版面配置中看到這些屬性。在這裡,您可以瞭解這些功能在使用 Flexbox 時的運作方式。

一組屬性可分為兩個群組。 空間分佈和對齊屬性。分配空間的屬性如下:

  • justify-content:主軸上的空間分佈情形。
  • align-content:跨軸的空間分佈。
  • place-content:設定上述這兩項屬性的簡寫。

在 Flexbox 中使用對齊的屬性:

  • align-self:對齊交叉軸上的單一項目。
  • align-items:對齊交叉軸上的所有項目群組。

如果您使用主軸,則屬性開頭是 justify-。在交叉軸上,開頭為 align-

主軸的發布空間

使用舊版 HTML 時,彈性項目會排成一列,主軸則有空間。 項目大小不足,無法完全填滿彈性容器。由於 justify-content 的初始值為 flex-start,因此項目會顯示在 Flex 容器的開頭。委刊項排在開頭,後面加上所有額外空間。

justify-content 屬性新增至 Flex 容器,並將其值設為 flex-end,接著委刊項會排在容器末端,且備用空間位於開頭。

.container {
  display: flex;
  justify-content: flex-end;
}

您也可以使用 justify-content: space-between 在項目之間分配空間。

在示範中試用部分值,並參閱 MDN 來瞭解完整的可能值。

前往 flex-direction: column

如將 flex-direction 變更為 column,則 justify-content 會在資料欄上執行。如要在以資料欄的形式工作時,在容器中保留備用空間,您必須為容器提供 heightblock-size。否則沒有備用儲存空間。

試試不同的值,這次使用 Flexbox 資料欄版面配置。

在彈性線之間分配空間

使用包裝的 Flex 容器時,您可能需要在交叉軸上發布空間。在這種情況下,您可以使用 align-content 屬性與 justify-content 相同的值。與預設會將項目對齊 flex-startjustify-content 不同,align-content 的初始值為 stretch。將屬性 align-content 新增至 Flex 容器,以變更該預設行為。

.container {
  align-content: center;
}

請在試用中試用這項功能。範例已包裝多行彈性項目,且容器含有 block-size,以便有足夠的空間。

place-content 簡寫

如要同時設定 justify-contentalign-content,您可以將 place-content 與一個或兩個值搭配使用。如果同時指定第一個值,則兩者會用於 align-content,第二個值則用於 justify-content

.container {
  place-content: space-between;
  /* sets both to space-between */
}

.container {
  place-content: center flex-end;
  /* wrapped lines on the cross axis are centered,
  on the main axis items are aligned to the end of the flex container */
}

在交叉軸上對齊項目

在交叉軸上,您也可以使用 align-itemsalign-self,對齊 Flex 線條中的項目。這種對齊方式的可用空間取決於 Flex 容器的高度,或對於包裝項目組合中的 Flex 線條。

align-self 的初始值為 stretch,因此根據預設,資料列中的彈性項目會延展至最高項目的高度。如要變更這項設定,請在任一彈性項目中加入 align-self 屬性。

.container {
  display: flex;
}

.item1 {
  align-self: flex-start;
}

請使用下列任一值對齊項目:

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

請參閱 MDN 的完整值清單

下一個示範版含有包含 flex-direction: row 的單行彈性項目。最後一個項目會定義 Flex 容器的高度。第一個項目的 align-self 屬性值為 flex-start。請嘗試變更該屬性的值,看看值在交叉軸上的移動情形。

align-self 屬性會套用至個別項目。align-items 屬性可以套用至彈性容器,將所有個別 align-self 屬性設為群組。

.container {
  display: flex;
  align-items: flex-start;
}

在下一個示範中,請嘗試變更 align-items 的值,讓交叉軸的所有項目以群組方式對齊。

為什麼在 Flexbox 中無法合理化自我?

Flex 項目可做為主軸上的一個群組。因此沒有將個別項目分割成該群組的概念。

在格線版面配置中,justify-selfjustify-items 屬性會在內嵌軸上運作,以便在格線區域內對齊該軸的項目。由於 Flex 版面配置會將項目視為群組,因此這些屬性無法在彈性環境中實作。

值得一提的是,Flexbox 可以與自動邊界完美搭配運作。如果您發現需要從群組分割一個項目,或將該群組拆成兩個群組,只要套用邊界即可。在以下範例中,最後一個項目的左邊界為 auto。自動邊界會依照套用的方向吸收所有空間。也就是說,這個項目會將項目推送到右側,進而分割群組。

如何將項目垂直和水平置中

對齊屬性可用來將項目置於另一個方塊內的中心。justify-content 屬性會對齊主軸 (列) 上的項目。交叉軸上的 align-items 屬性。

.container {
  width: 400px;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}

隨堂測驗

測試您對 Flexbox 的相關知識

.container {
  display: flex;
  direction: ltr;
}

若要與 Flexbox 垂直對齊,請使用

比對關鍵字
很好
左右對齊關鍵字
抱歉
.container {
  display: flex;
  direction: ltr;
}

若要水平對齊 Flexbox,請使用

比對關鍵字
抱歉
左右對齊關鍵字
很好
.container {
  display: flex;
  direction: ltr;
}

根據預設,Flex 項目會與 stretch 對齊。如要將內容大小用於子項作品,您應使用以下哪一種樣式?

justify-content: flex-start
左右對齊屬性是用來水平對齊,而非垂直。
align-content: start
content 會對齊彈性線,而非子項項目對齊。
height: auto
不會產生任何影響。
align-items: flex-start
是,我們想將其垂直對齊「top」或開始,這樣可以移除預設的延展值,並改用內容高度。

資源