CSS Podcast - 010: Flexbox
在回應式設計中,設計模式可能會很棘手,是一種內嵌於部分內容的側欄。對於可視區域空間而言,這個模式十分實用,但如果發生空間壓縮的情況,這種固定版面配置可能就會造成問題。
彈性 Box 版面配置模型 (flexbox) 是專為單維內容設計的版面配置模型。擅長擷取多種大小不一的項目,並為這些項目傳回最佳版面配置。
對於此側欄模式,這是理想的版面配置模型。Flexbox 不僅能協助將側欄和以內嵌方式顯示內容,當空間不足時,側欄也會分行。使用 Flexbox 時,您可以改為提供彈性的邊界,以提示內容的顯示方式,而不需要設定瀏覽器遵循的彈性尺寸。
Flex 版面配置提供哪些功能?
Flex 版面配置提供下列功能,您可在本指南中探索。
- 它們可以以資料列或資料欄的形式顯示。
- 這些規則遵循文件的撰寫模式。
- 根據預設,這些是單行,但可能要求換行。
- 版面配置中的項目可透過視覺方式重新排序,與 DOM 中的順序相反。
- 空間可以在項目中分配,以便依據父項的可用空間而放大和縮小。
- 您可以使用 Box Alignment 屬性,在項目周圍分配空間和彈性線。
- 項目本身可以對齊跨軸。
主軸和交叉軸
瞭解 Flexbox 的關鍵在於瞭解主軸和交叉軸的概念。主軸是由 flex-direction
屬性設定的。如果為 row
,您的主要軸會沿著資料列顯示,如果為 column
,則主要軸位於欄上。
Flex 項目會一個在主軸上移動。請記住:我們能處理諸多事項,試圖為小組打造出最完善的版面配置。
交叉軸則是從另一個方向指向主軸,因此如果 flex-direction
為 row
,則交叉軸會沿著資料欄執行。
您可以執行兩項操作。
您可以個別移動項目,也可以一次移動項目,讓這些項目會彼此對齊及彈性容器。此外,如果您有包裝的彈性行,您可以將這些行視為群組,控制這些行所指派空間的方式。您將會瞭解這在本指南中實際的運作方式。現在請注意,主軸遵循 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-reverse
和 column-reverse
值就是很好的範例。系統只會依照視覺順序進行重新排序,而不會對邏輯順序進行。這點很重要,因為邏輯順序是螢幕閱讀器讀出內容的順序,所有使用鍵盤導覽的使用者都會遵循。
請觀看以下影片,您可以瞭解在反向列版面配置中,由於鍵盤導覽是遵循 DOM 而非視覺顯示,因此連結之間的分頁會中斷連線。
任何可以變更 Flexbox 或格線中項目順序的元件,都可能造成這個問題。因此,任何重新排序都應進行全面測試,確保網站不會對部分使用者使用網站造成困難。
如需詳細資訊,請參閱:
書寫模式與方向
根據預設,Flex 項目會排成一列。資料列會按照書寫模式和指令碼方向的語句流動。也就是說,如果你使用阿拉伯文,且文字方向為由右至左 (rtl) 行,則項目會排在右邊。定位點順序也會從右側開始,因為這是阿拉伯語句子的閱讀方式。
如果您使用垂直書寫模式 (例如某些日文字體),則系統會從上到下垂直執行一列。在這個示範中,請嘗試變更使用垂直書寫模式的 flex-direction
。
因此,Flex 項目的預設行為會連結至文件的寫作模式。大部分的教學課程都是以英文或其他水平方向編寫,由左至右書寫模式。如此一來,即可輕鬆假設彈性委刊項會在左側,並水平執行。
由於我們探討的是主軸和交叉軸,再加上寫出模式,我們所說的,在 Flexbox 中提到的「start」和「end」,不比頂端、底部、左側和右側,可能更容易理解。每個軸都有開頭和結尾。主軸的開頭稱為「main-start」。因此我們的彈性委刊項一開始會從主啟動。該軸的結尾為「main-end」。交叉軸的開頭為交叉開始,結束交叉點。
包裝 Flex 項目
flex-wrap
屬性的初始值為 nowrap
。這表示如果容器空間不足,項目就會溢位。
使用初始值顯示的項目會盡可能縮小,直到溢位到 min-content
的大小為止。
如要使項目包裝,請將 flex-wrap: wrap
新增至 Flex 容器。
.container {
display: flex;
flex-wrap: wrap;
}
當 Flex 容器封裝時,會建立多個彈性線。就空間分配而言,每一行都像是一個新的彈性容器。因此,如果您要包裝資料列,就無法在第 2 列中與第 1 列上方的內容對齊。這是一個 Flexbox 的意思。您可以控制單一軸、資料列或資料欄的對齊方式,而不能同時控制兩者的對齊方式,就像在格線中一樣。
Flex-flow
您可以使用簡寫 flex-flow
設定 flex-direction
和 flex-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-grow
、flex-shrink
和 flex-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
,因此這些項目的空間均等長,且空間共享同等。
讓商品以不同的速率成長
您不必為所有項目提供 1
的 flex-grow
因子。您可以為彈性項目提供不同的 flex-grow
因素。在下方的示範中,第一個項目有 flex: 1
、第二個 flex: 2
和第三個 flex: 3
。
這些項目從 0
增加時,Flex 容器中的可用空間就會與六個共用。一個部分會給第一個項目
兩個部分到第二部分,第三部分則給第三部分
您可以在 auto
的 flex-basis
中執行相同操作,但您需要指定三個值。第一個值是 flex-grow
、第二個 flex-shrink
和第三個 flex-basis
。
.item1 {
flex: 1 1 auto;
}
.item2 {
flex: 2 1 auto;
}
這種情況較不常見,因為使用 auto
的 flex-basis
可讓瀏覽器瞭解空間分佈情形。如果您想讓項目成長幅度比演算法決定多一些,但或許會有幫助。
重新排序 Flex 項目
您可以使用 order
屬性重新排序 Flex 容器中的項目。這個屬性可按照一般群組中的項目順序排列。
項目會按照 flex-direction
指定的方向排列,最低值優先。如果多個項目擁有相同值,系統會與其他項目一起顯示。
以下範例會示範這個排序方式。
隨堂測驗
測試您對 Flexbox 的相關知識
flex-direction
預設為
row
column
根據預設,Flex 容器會納入子項。
flex-wrap: wrap
與 display: 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
會在資料欄上執行。如要在以資料欄的形式工作時,在容器中保留備用空間,您必須為容器提供 height
或 block-size
。否則沒有備用儲存空間。
試試不同的值,這次使用 Flexbox 資料欄版面配置。
在彈性線之間分配空間
使用包裝的 Flex 容器時,您可能需要在交叉軸上發布空間。在這種情況下,您可以使用 align-content
屬性與 justify-content
相同的值。與預設會將項目對齊 flex-start
的 justify-content
不同,align-content
的初始值為 stretch
。將屬性 align-content
新增至 Flex 容器,以變更該預設行為。
.container {
align-content: center;
}
請在試用中試用這項功能。範例已包裝多行彈性項目,且容器含有 block-size
,以便有足夠的空間。
place-content
簡寫
如要同時設定 justify-content
和 align-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-items
和 align-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-self
和 justify-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