在彈性容器中對齊專案

Flexbox 之所以如此有用,原因之一是它能實現良好的對齊,包括提供一種快速垂直居中元素的方法。在本指南中,我們將深入探討對齊和內容對齊屬性在 Flexbox 中的工作原理。

在 Flexbox 中使用對齊

Flexbox 提供了多個屬性來控制對齊和間距,其中 align-itemsjustify-content 是實現元素居中的基礎。要居中一個元素,我們使用 align-items 屬性在交叉軸上對齊專案,在本例中即為垂直方向的塊軸。我們使用 justify-content 在主軸上對齊專案,在本例中即為水平方向的行內軸。

The cross axis is the vertical axis and the main axis is the horizontal axis.

在下面的程式碼示例中,更改容器或巢狀元素的大小。巢狀的元素始終保持居中。

html
<div class="box">
  <div></div>
</div>
css
.box {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dotted rgb(96 139 168);
}

.box div {
  width: 100px;
  height: 100px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

用於控制 Flexbox 中對齊的屬性

我們將在本指南中介紹的屬性如下:

  • justify-content:控制所有專案在主軸上的對齊方式。
  • align-items:控制所有專案在交叉軸上的對齊方式。
  • align-self:控制單個彈性專案在交叉軸上的對齊方式。
  • align-content:控制交叉軸上彈性行之間的空間。
  • gapcolumn-gaprow-gap:用於在彈性專案之間建立間隙或間距。

我們還將探討如何在 Flexbox 中使用 auto 外邊距進行對齊。

在交叉軸上對齊專案

在彈性容器上設定的 align-items 屬性,以及在彈性專案上設定的 align-self 屬性,控制彈性專案在交叉軸上的對齊方式。如果 flex-directionrow,交叉軸沿列向下延伸;如果 flex-directioncolumn,交叉軸沿行延伸。

在這個基礎的彈性盒子示例中,我們使用了交叉軸對齊。當我們給一個容器新增 display: flex 時,其子項會變成彈性專案,並排列成一行。預設情況下,它們都會拉伸以匹配最高專案的高度,因為最高的專案定義了交叉軸上專案的高度。如果彈性容器設定了高度,那麼無論每個專案中有多少內容,這些專案都會拉伸到該高度。

Three items, one with additional text causing it to be taller than the others.

Three items stretched to 200 pixels tall

專案變成相同高度的原因是,控制交叉軸對齊的 align-items 屬性的初始值為 stretch

我們可以使用其他值來控制專案的對齊方式:

  • align-items: stretch
  • align-items: flex-start
  • align-items: flex-end
  • align-items: start
  • align-items: end
  • align-items: center
  • align-items: baseline
  • align-items: first baseline
  • align-items: last baseline

在下面的示例中,align-items 的值為 stretch。嘗試其他值,看看專案在彈性容器中是如何相互對齊的。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three <br />has <br />extra <br />text</div>
</div>
css
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: stretch;
}

.box div {
  width: 100px;
  background-color: rgb(96 139 168 / 0.2);
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
}

使用 align-self 對齊單個專案

align-items 屬性將 align-self 屬性作為一個組應用於所有彈性專案。這意味著你可以顯式宣告 align-self 屬性來針對單個專案。align-self 屬性接受與 align-items 相同的所有值,外加一個 auto 值,它會將該值重置為彈性容器上定義的值。

在接下來的即時示例中,彈性容器設定了 align-items: flex-start,這意味著所有專案都對齊到交叉軸的起始位置。使用 first-child 選擇器,第一個專案被設定為 align-self: stretch。另一個帶有 selected 類的專案設定了 align-self: center。更改 align-items 的值或更改單個專案上 align-self 的值,看看它是如何工作的。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div class="selected">Three</div>
  <div>Four</div>
</div>
css
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: flex-start;
  height: 200px;
}
.box div {
  background-color: rgb(96 139 168 / 0.2);
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  padding: 20px;
}
.box > *:first-child {
  align-self: stretch;
}
.box .selected {
  align-self: center;
}

更改主軸

到目前為止,我們已經探討了在從上到下書寫的語言中,當 flex-direction 預設為 row 時的對齊行為,此時主軸是水平的,交叉軸是垂直的。

Three items, the first aligned to flex-start, second to center, third to flex-end. Aligning on the vertical axis.

保持相同的書寫模式,當 flex-direction 變為 column 時,align-itemsalign-self 屬性將使專案向左和向右對齊,而不是向上和向下;這些屬性仍然是在交叉軸上對齊專案,但此時交叉軸是水平的!

Three items, the first aligned to flex-start, second to center, third to flex-end. Aligning on the horizontal axis.

你可以在下面的示例中嘗試這一點,該示例的彈性容器設定了 flex-direction: column,但其他方面與前一個示例完全相同。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div class="selected">Three</div>
  <div>Four</div>
</div>
css
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
}
.box div {
  background-color: rgb(96 139 168 / 0.2);
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  padding: 20px;
}
.box > *:first-child {
  align-self: stretch;
}
.box .selected {
  align-self: center;
}

使用 align-content 屬性在交叉軸上對齊內容

到目前為止,我們一直專注於在由彈性容器定義的區域內對齊單個或多個專案,且這些專案只佔一行。當允許彈性專案換行到多行時,可以使用 align-content 屬性來控制行與行之間的空間分佈,這也被稱為堆疊彈性行

為了讓 align-content 生效,彈性容器的交叉軸尺寸(在本例中是高度)必須大於顯示專案所需的尺寸。然後它會作用於所有專案作為一個整體。align-content 的值決定了如何處理額外的可用空間,以及整個專案集合在其中的對齊方式。

align-content 屬性接受以下值:

  • align-content: flex-start
  • align-content: flex-end
  • align-content: start
  • align-content: end
  • align-content: center
  • align-content: space-between
  • align-content: space-around
  • align-content: space-evenly
  • align-content: stretch
  • align-content: normal(行為與 stretch 相同)
  • align-content: baseline
  • align-content: first baseline
  • align-content: last baseline

在下面的即時示例中,彈性容器的高度為 400 畫素,這比顯示我們的專案所需的空間要多。align-content 的值為 space-between,這意味著可用空間被分配在彈性行之間,這些行在交叉軸上與容器的起始和結束邊緣齊平。

嘗試其他值,看看 align-content 屬性是如何工作的。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
  <div>Seven</div>
  <div>Eight</div>
</div>
css
.box {
  width: 450px;
  border: 2px dotted rgb(96 139 168);
  display: flex;
  flex-wrap: wrap;
  height: 300px;
  align-content: space-between;
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  flex: 1 1 100px;
}

.box div {
  background-color: rgb(96 139 168 / 0.2);
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  padding: 20px;
}

我們可以再次將 flex-direction 切換為 column,以觀察當按列工作時該屬性的行為。和之前一樣,我們需要在交叉軸上有足夠的空間,以便在顯示完所有專案後還有一些可用空間。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
  <div>Seven</div>
  <div>Eight</div>
</div>
css
.box {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  width: 400px;
  height: 300px;
  align-content: space-between;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  flex: 1 1 100px;
}

.box div {
  background-color: rgb(96 139 168 / 0.2);
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  padding: 20px;
}

在主軸上對齊內容

現在我們已經瞭解了對齊在交叉軸上的工作方式,我們可以看看主軸。在這裡,我們只有一個可用的屬性——justify-content。這是因為在主軸上,我們只將專案作為一個組來處理。透過 justify-content,我們可以控制當有多餘空間時如何處理這些空間。

在我們最初的 display: flex 示例中,專案以行的形式顯示,並全部在容器的起始位置對齊。這是因為 justify-content 的初始值為 normal,其行為與 start 相同。任何可用的空間都會被放置在專案的末尾。

Three items, each 100 pixels wide in a 500 pixel container. The available space is at the end of the items.

baseline 值在這個維度上不適用。除此之外,justify-content 屬性接受與 align-content 相同的值。

  • justify-content: flex-start
  • justify-content: flex-end
  • justify-content: start
  • justify-content: end
  • justify-content: left
  • justify-content: right
  • justify-content: center
  • justify-content: space-between
  • justify-content: space-around
  • justify-content: space-evenly
  • justify-content: stretch(行為與 start 相同)
  • justify-content: normal(行為與 stretch 相同,而 stretch 的行為又與 start 相同)

在下面的示例中,justify-content 的值為 space-between。顯示完專案後,剩餘的可用空間被分配在專案之間。最左和最右的專案與容器的起始和結束邊緣齊平。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
</div>
css
.box {
  display: flex;
  justify-content: space-between;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

如果因為 flex-direction 設定為 column 而使主軸處於塊方向,那麼只要彈性容器中有可分配的空間,justify-content 就會在該維度上分配專案之間的空間。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
</div>
css
.box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 300px;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

對齊與書寫模式

請記住,對於所有這些對齊方法,startend 的值都與書寫模式相關。如果 justify-content 的值為 start,且書寫模式是從左到右(如英語),專案將從容器的左側開始對齊。

Three items lined up on the left

然而,如果書寫模式是從右到左(如阿拉伯語),專案將從容器的右側開始對齊。

Three items lined up from the right

下面的即時示例將 direction 屬性設定為 rtl,以強制我們的專案採用從右到左的流向。你可以移除這個設定,或更改 justify-content 的值,以觀察當行內方向的起始點在右側時 Flexbox 的行為。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
</div>
css
.box {
  direction: rtl;
  display: flex;
  justify-content: flex-end;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

對齊與 flex-direction

如果你改變 flex-direction 屬性,例如使用 row-reverse 而不是 row,行的 start 方向也會改變。

在下一個示例中,flex-direction: row-reversejustify-content: flex-end 定義了彈性容器內專案的方向和位置。在從左到右的語言中,專案在左側對齊。嘗試將 flex-direction: row-reverse 改為 flex-direction: row。你會看到專案現在移動到了右側,並且專案的視覺順序也反轉了。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
</div>
css
.box {
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

雖然這一切可能看起來有點令人困惑,但要記住的規則是,除非你做些什麼來改變它,否則彈性專案會按照文件語言中單詞沿行內(row)軸的排列方向來佈局。startflex-start 將位於文字句子的起始位置。

Diagram showing start on the left and end on the right.

你可以透過選擇 flex-direction: column 將它們切換為文件語言的塊方向顯示。然後,startflex-start 將位於第一個文字段落的頂部。

Diagram showing start at the top and end at the bottom.

如果你將 flex-direction 改為某個反向值,它們將從末端軸開始佈局,並且順序與文件語言中單詞的書寫方式相反。然後,startflex-start 會改變到該軸的末端——也就是,如果按行工作,行會換行的位置;或者在塊方向上,最後一個文字段落的末尾。

Diagram showing start on the right and end on the left.

Diagram showing end at the top and start at the bottom

使用 auto 外邊距實現主軸對齊

在主軸上,我們沒有 justify-itemsjustify-self 屬性可用,因為我們的專案在該軸上被視為一個組。然而,透過結合使用 auto 外邊距和 Flexbox,可以實現一些單獨的對齊,以便將一個專案或一組專案與其他專案分開。

一個常見的模式是導航欄,其中一些關鍵專案對齊到右側,而主要組在左側。你可能會認為這應該是 justify-self 屬性的用例。然而,請考慮下圖。舉個例子,看下面這張圖,一邊有三個專案,另一邊有兩個。如果 justify-self 作用於彈性專案並設定在專案 d 上,它也會改變其後專案 e 的對齊方式,這可能不是我們想要的。

Five items, in two groups. Three on the left and two on the right.

相反,可以透過 CSS 外邊距將專案 d 推到另一邊。

在這個即時示例中,透過將第四個專案的 margin-left 設定為 auto,使其與前三個專案分開。auto 會在其軸向上佔據所有可用空間。這與使用 margin 的 auto 左右外邊距來居中一個塊的原理相同。每一邊都試圖佔據儘可能多的空間,從而將塊推到中間。

在這個即時示例中,彈性專案使用基本的 flex 值排列成一行,並且在第四個專案上設定的 push 類應用了 margin-left: auto。嘗試移除第四個專案上的類,或將該類新增到不同的專案上,看看它是如何工作的。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div class="push">Four</div>
  <div>Five</div>
</div>
css
.box {
  display: flex;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.push {
  margin-left: auto;
}

在專案之間建立間距

要在彈性專案之間建立間隙,請使用 gapcolumn-gaprow-gap 屬性。column-gap 屬性在一行中的專案之間建立間隙。row-gap 屬性在設定了 flex-wrapwrap 時,在彈性行之間建立間隙。

gap 屬性是設定 row-gapcolumn-gap 的簡寫。彈性專案或彈性行之間的間隙取決於方向。如果 flex-direction 屬性建立了行,則第一個值定義彈性行之間的間隙,第二個值定義每行內專案之間的間隙。對於列(當 flex-direction 設定為 columncolumn-reverse 時),第一個值定義彈性專案之間的間隙,第二個值定義彈性行之間的間隙。

html
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
</div>
css
.box {
  display: flex;
  flex-wrap: wrap;
  row-gap: 10px;
  column-gap: 2em;
  border: 2px dotted rgb(96 139 168);
}

.box > * {
  flex: 1;
  padding: 20px;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

另見