flexbox 的基本概念
彈性盒子佈局模組(通常簡稱為 flexbox)是一種一維佈局模型,用於在專案之間分配空間,幷包含多種對齊功能。本文概述了 flexbox 的主要功能,我們將在本指南的其餘部分中更詳細地探討這些功能。
當我們描述 flexbox 是一維時,我們指的是 flexbox 一次只處理一個維度的佈局——要麼是行,要麼是列。這與 CSS Grid Layout 的二維模型形成對比,後者同時控制行和列。
Flexbox 的兩個軸
使用 flexbox 時,你需要考慮兩個軸——*主軸*和*側軸*。主軸由 flex-direction 屬性定義,側軸垂直於主軸執行。我們使用 flexbox 所做的一切都與這些軸相關,因此從一開始就瞭解它們的工作原理是值得的。
主軸
主軸由 flex-direction 定義,它有四個可能的值
rowrow-reversecolumncolumn-reverse
如果你選擇 row 或 row-reverse,你的主軸將沿行方向在**行內方向**上執行。
選擇 column 或 column-reverse,你的主軸將沿**塊方向**執行,從頁面的頂部到底部。
側軸
側軸垂直於主軸。因此,如果你的 flex-direction(主軸)設定為 row 或 row-reverse,則側軸沿列向下執行。
如果你的主軸是 column 或 column-reverse,那麼側軸沿行執行。
起始線和結束線
另一個重要的理解領域是 flexbox 不對文件的書寫模式做任何假設。Flexbox 不僅僅假設所有文字行都從文件的左上角開始,然後向右側執行,新行一個接一個地出現。相反,它支援所有書寫模式,就像其他邏輯屬性和值一樣。
你可以在後面的文章中閱讀更多關於 flexbox 和書寫模式之間關係的資訊;但是,以下描述應該有助於解釋為什麼我們不談論左和右以及上和下,而是描述我們的彈性專案流動的方向。
如果 flex-direction 是 row,並且我正在使用英語,那麼主軸的起始邊將在左側,結束邊將在右側。
如果我使用阿拉伯語,那麼我的主軸的起始邊將在右側,結束邊將在左側。
在這兩種情況下,側軸的起始邊都在彈性容器的頂部,結束邊都在底部,因為這兩種語言都具有水平書寫模式。
過了一段時間,思考起始和結束而不是左和右會變得很自然,並且當你處理其他遵循相同模式的佈局方法(例如 CSS Grid Layout)時,這將對你很有用。
彈性容器
使用 flexbox 進行佈局的文件區域稱為**彈性容器**。要建立彈性容器,請將其display屬性設定為flex。當我們這樣做時,該容器的直接子元素將成為**彈性專案**。你可以使用inline flex或inline-flex用於行內彈性容器,或使用block flex或flex用於塊級彈性容器,顯式控制容器本身是以行內還是塊級格式化上下文顯示。
初始值
與 CSS 中的所有屬性一樣,定義了一些初始值,因此新彈性容器的內容將按以下方式執行
- 專案以行顯示(
flex-direction屬性的預設值為row)。 - 專案從主軸的起始邊緣開始。
- 專案在主維度上不拉伸但可以收縮(彈性專案的
flex-grow屬性的預設值為0,其flex-shrink屬性的預設值為1)。 - 專案將拉伸以填充側軸的大小(
align-items屬性的預設值為stretch)。 - 彈性專案的
flex-basis屬性的預設值為auto。這意味著,在每種情況下,它都將等於水平書寫模式下的彈性專案width,以及垂直書寫模式下的彈性專案height。如果相應的width/height也設定為auto,則改用flex-basis的content值。 - 所有專案都將在一行中(
flex-wrap屬性的預設值為nowrap),如果它們的組合width/height超過了包含元素的width/height,它們將溢位其容器。
結果是你的專案都會排成一排,以內容的大小作為它們在主軸上的大小。如果專案數量超出容器所能容納的範圍,它們將不會換行,而是會溢位。如果有些專案比其他專案高,所有專案都將沿著側軸的整個長度拉伸。
你可以在下面的即時示例中看到它的樣子。點選“播放”在 MDN Playground 中開啟示例,並編輯專案或新增新專案以嘗試 flexbox 的初始行為
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three <br />has <br />extra <br />text</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
}
改變 flex-direction
向彈性容器新增 flex-direction 屬性可以讓我們改變彈性專案的顯示方向。設定 flex-direction: row-reverse 將使專案沿行顯示,但起始線和結束線會交換。
如果我們將 flex-direction 更改為 column,主軸將切換,我們的專案現在以列的形式顯示。設定為 column-reverse,起始線和結束線將再次交換。
下面的即時示例將 flex-direction 設定為 row-reverse。嘗試其他值——row、column 和 column-reverse——看看內容會發生什麼。
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
flex-direction: row-reverse;
}
使用 flex-wrap 的多行彈性容器
雖然 flexbox 是一維模型,但可以使 flex 專案在多行中換行。如果你這樣做,你應該將每行視為一個新的 flex 容器。任何空間分佈都將發生在每行中,而與前一行或後續行無關。
要實現換行行為,請新增屬性 flex-wrap,並將其值設為 wrap。現在,如果你的專案太大而無法全部顯示在一行中,它們將換到另一行。下面的即時示例包含已設定 width 的專案。專案的總寬度對於彈性容器來說太寬了。由於 flex-wrap 設定為 wrap,專案將在多行中換行。如果將其設定為 nowrap(這是初始值),它們將收縮以適應容器。它們之所以收縮,是因為它們使用了初始的 flexbox 值,包括 flex-shrink: 1,這允許專案收縮。如果專案無法收縮,或者無法收縮到足以適應的程度,使用 nowrap 將導致溢位。
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
width: 200px;
}
.box {
width: 500px;
border: 2px dotted rgb(96 139 168);
display: flex;
flex-wrap: wrap;
}
在指南 掌握彈性專案的換行 中瞭解更多關於換行彈性專案的資訊。
flex-flow 簡寫
你可以將 flex-direction 和 flex-wrap 這兩個屬性組合成 flex-flow 簡寫。
在下面的即時示例中,嘗試將第一個值更改為 flex-direction 的允許值之一——row、row-reverse、column 或 column-reverse,同時將第二個值更改為 wrap 和 nowrap。
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
width: 200px;
}
.box {
width: 500px;
border: 2px dotted rgb(96 139 168);
display: flex;
flex-flow: row wrap;
}
應用於彈性專案的屬性
為了控制每個彈性專案的行內大小,我們直接透過三個屬性來控制它們
我們將在下面簡要介紹這些屬性,但如果你想獲取更全面的資訊,請檢視控制主軸上彈性專案的比例指南。
在我們理解這些屬性之前,我們需要考慮**可用空間**的概念。當我們改變這些彈性屬性的值時,我們正在改變可用空間在專案之間的分佈方式。當我們要對齊專案時,可用空間的概念也很重要。
如果一個容器寬 500 畫素,裡面有三個寬 100 畫素的專案,那麼我們佈局專案所需的空間就是 300 畫素。這樣就剩下 200 畫素的可用空間。如果我們不改變初始值,那麼 flexbox 會將這些空間放在最後一個專案之後。
如果我們希望專案增長並填充空間,那麼我們需要一種方法來在專案之間分配剩餘空間。我們應用於專案本身的 flex 屬性,可以決定這些可用空間應該如何分配給兄弟彈性專案。
flex-basis 屬性
flex-basis 定義了該專案的大小,就其作為可用空間留下的空間而言。此屬性的初始值為 auto — 在這種情況下,瀏覽器會檢視專案是否具有大小。在上面的示例中,所有專案的寬度都是 100 畫素。這被用作 flex-basis。
如果專案沒有大小,則使用內容的大小作為 flex-basis。這就是為什麼當我們僅在父元素上宣告 display: flex 來建立彈性專案時,所有專案都排成一行,並且只佔用顯示其內容所需的空間。
flex-grow 屬性
當 flex-grow 屬性設定為正整數時,如果有可用空間,彈性專案可以沿主軸從其 flex-basis 增長。專案是否拉伸以佔據該軸上的所有可用空間,或者僅僅是可用空間的一部分,取決於其他專案是否也允許增長以及它們的 flex-grow 屬性的值。
每個具有正值的專案都會根據其 flex-grow 值佔用一部分可用空間。如果我們將上面示例中的所有專案都賦予 flex-grow 值為 1,那麼彈性容器中的可用空間將平均分配給我們的專案,並且它們將沿主軸拉伸以填充容器。如果我們將第一個專案賦予 flex-grow 值為 2,而其他專案各賦予 1,則總共有 4 份;第一項將獲得可用空間的 2 份(在上面的示例中,200px 中的 100px),其餘兩項各獲得 1 份(200px 中的 50px)。
flex-shrink 屬性
flex-grow 屬性處理在主軸上增加空間,而 flex-shrink 屬性則控制如何減小空間。如果容器中沒有足夠的空間來佈局我們的專案,並且 flex-shrink 設定為正整數,那麼專案可以變得比 flex-basis 小。與 flex-grow 一樣,可以分配不同的值以使一個專案比其他專案收縮得更快——設定了更高 flex-shrink 值的專案將比具有較低值的兄弟專案收縮得更快。
專案可以收縮到其 min-content 大小。在計算實際收縮量時會考慮這個最小大小,這意味著 flex-shrink 在行為上可能看起來不如 flex-grow 一致。因此,我們將在文章 控制主軸上專案的比例 中更詳細地研究此演算法的工作原理。
注意:flex-grow 和 flex-shrink 的這些值是比例。通常,如果我們所有專案都設定為 flex: 1 1 200px,然後希望其中一個專案以兩倍的速度增長,我們會將該專案設定為 flex: 2 1 200px。但是,如果你願意,也可以使用 flex: 10 1 200px 和 flex: 20 1 200px。
flex 屬性的簡寫值
你很少會看到 flex-grow、flex-shrink 和 flex-basis 屬性單獨使用;相反,它們被組合成 flex 簡寫。flex 簡寫允許你按此順序設定這三個值——flex-grow、flex-shrink、flex-basis。
下面的即時示例允許你測試 flex 簡寫的不同值;請記住,第一個值是 flex-grow。將其設定為正值意味著專案可以增長。第二個是 flex-shrink — 設為正值時,專案可以收縮,但前提是它們的總值溢位主軸。最後一個值是 flex-basis;這是專案作為其增長和收縮的基礎值。
<div class="box">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
}
.one {
flex: 1 1 auto;
}
.two {
flex: 1 1 auto;
}
.three {
flex: 1 1 auto;
}
還有一些預定義的簡寫值涵蓋了大多數用例。你經常會在教程中看到這些,並且在許多情況下,這些就是你所需要使用的全部。預定義值如下
flex: initialflex: autoflex: noneflex: <positive-number>
initial 值是一個CSS 全域性關鍵字,表示屬性的初始值。設定 flex: initial 會將專案重置為三個長手屬性的初始值,這與 flex: 0 1 auto 相同。flex-grow 的初始值為 0,因此專案不會超過其 flex-basis 大小。flex-shrink 的初始值為 1,因此專案在需要時可以收縮,而不是溢位。flex-basis 的初始值為 auto。專案將使用在主維度上設定的任何大小,或者它們將從內容大小獲取其大小。
使用 flex: auto 與使用 flex: 1 1 auto 相同;這類似於 flex: initial,只是專案在需要時可以增長並填充容器以及收縮。
使用 flex: none 將建立完全不可伸縮的彈性專案。它就像你寫了 flex: 0 0 auto。專案不能增長或收縮,並將使用 flex-basis 為 auto 的 flexbox 進行佈局。
你在教程中經常看到的簡寫是 flex: 1 或 flex: 2 等等。這與分別編寫 flex: 1 1 0 或 flex: 2 1 0 等等是相同的。由於 flex-basis: 0,專案獲得最小尺寸,然後按比例增長以填充可用空間。在這種情況下,flex-shrink 值 1 是多餘的,因為專案從最小尺寸開始——它們沒有被賦予任何可能導致它們溢位彈性容器的尺寸。
在下面的即時示例中嘗試這些簡寫值。
<div class="box">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
}
.one {
flex: 1;
}
.two {
flex: 1;
}
.three {
flex: 1;
}
專案之間的對齊、對齊和自由空間分佈
Flexbox 的一個關鍵特性是能夠在主軸和側軸上對齊和對齊專案,以及在彈性專案之間分配空間。請注意,這些屬性設定在彈性容器上,而不是專案本身上。
align-items
align-items 屬性在側軸上對齊所有彈性專案。
此屬性的初始值為 stretch,這就是為什麼彈性專案預設情況下會拉伸到彈性容器的高度(如果 flex-direction 設定為 column 或 column-reverse,則為寬度)。此高度可能來自容器中最高的專案,或在彈性容器本身上設定的大小。
你可以選擇將 align-items 設定為 flex-start,或簡單地設定為 start,以便使專案對齊到彈性容器的起始位置;設定為 flex-end,或簡單地設定為 end,以便對齊到結束位置;或者設定為 center 以便對齊到中心。在即時示例中嘗試一下——我已經為彈性容器設定了高度,以便你可以看到專案如何在容器內移動。看看將 align-items 的值設定為以下值時會發生什麼
stretchflex-startflex-endstartendcenterbaselinelast baseline
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three <br />has <br />extra <br />text</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
width: 500px;
height: 130px;
border: 2px dotted rgb(96 139 168);
display: flex;
align-items: flex-start;
}
align-items 設定在彈性容器上,並影響所有彈性專案。如果你想以不同於其他專案的方式對齊某個彈性專案,你可以在該彈性專案上設定 align-self。
justify-content
justify-content 屬性用於在主軸上對齊專案,即 flex-direction 設定的流向。初始值為 flex-start,它會將專案對齊到容器的起始邊緣,但你也可以將值設定為 flex-end 以對齊到末尾,或者設定為 center 以對齊到中心。
你還可以使用 space-between 值,它會在專案佈局後將所有剩餘空間均勻地分配給專案,從而使每個專案之間都有相等的空間。要使每個專案左右(或列的上下)都有相等的空間,請使用 space-around 值。使用 space-around,專案兩端都有半個空間的間距。或者,要使專案周圍有相等的空間,請使用 space-evenly 值。使用 space-evenly,專案兩端都有一個完整空間的間距。
在即時示例中嘗試以下 justify-content 值
startendleftrightnormalflex-startflex-endcenterspace-aroundspace-betweenspace-evenlystretch
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
justify-content: flex-start;
}
文章 在彈性容器中對齊專案 更深入地探討了這些屬性,以便更好地理解它們的工作原理。然而,這些基本示例在大多數用例中都很有用。
justify-items
在彈性盒佈局中,justify-items 屬性被忽略。
place-items 和 place-content
place-items 屬性是 align-items 和 justify-items 的簡寫屬性。如果設定在彈性容器上,它將設定對齊方式而非對齊理由,因為 justify-items 在 flexbox 中被忽略。
還有另一個簡寫屬性,place-content,它定義了 align-content 和 justify-content 屬性。align-content 屬性隻影響換行的彈性容器,並在在彈性容器中對齊專案中討論。
後續步驟
閱讀本文後,你應對 flexbox 的基本功能有所瞭解。在下一篇文章中,我們將探討 此規範如何與其他 CSS 部分相關聯。