還在爲垂直居中苦惱?CSS 佈局利器 flexbox 輕輕鬆鬆幫你搞定

傳統的 CSS 佈局方式是基於盒模型(它是根據盒子與父盒子以及兄弟盒子的關係確定大小位置的算法),實現時依賴於 block, inline, table, position, float 這些屬性,但對於一些特殊佈局不易實現,比如垂直居中

Flexbox Layout 是一種新的佈局方式,被稱爲彈性佈局,它使得子元素(items)可以靈活的、響應式的適應父容器(flex container)的空間,即使子元素的大小未知或是動態,並且可以很容易實現元素的水平和垂直對齊。

盒模型是基於 blockinline 的流動方向進行佈局,而 flex 佈局則是基於彈性流方向(flex-flow directions),基本思想如下圖所示。

flex-direction-terms.svg

flex 容器內的子元素會沿着 main axis(從 main-startmain-end )或 cross axis(從 cross-startcross-end)進行佈局,其中:

  • main axis - 主軸,子元素排列的基本軸,要注意,它不一定是水平的,這取決於 flex-direction 屬性的配置
  • main-start | main-end - 子元素從 main-start 開始到 main-end 彈性的放置在容器中,默認都在一行排列,不換行, 除非設置 flex-wrap 屬性
  • main size - 子元素的主尺寸,如果主軸是水平的,那 width 是主尺寸;垂直的,那 height 是主尺寸
  • cross axis - 垂直於主軸的軸,稱之爲交叉軸,方向取決於主軸的方向
  • cross-start | cross-end - 當子元素換行時,每行則從 cross-start 開始到 cross-end 排列
  • cross size - 與 main size 同理,只不過剛好相反

Flex Container

使用以下代碼就可以將一個 HTML 元素指定爲 flex 佈局:

.container {
  display: flex; /* or inline-flex */
}

這個元素稱爲 Flex Container,內部其他 HTML 元素被稱爲 Flex Itemsflex 容器 有 6 個屬性:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

flex-direction

flex-direction.svg

確定主軸的方向,也就是內部元素的彈性排列方向。如果不考慮換行,Flexbox 是單向佈局的概念,始終將元素放置在水平行垂直列中。

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}
  • row(默認): 主軸爲水平方向,從左到右排列
  • row-reverse: 主軸爲水平方向,從右到左排列
  • column: 主軸爲垂直方向,從上到下排列
  • column-reverse: 主軸爲垂直方向,從下到上排列

flex-wrap

flex-wrap.svg

默認情況下,子元素不會換行,只會在同一行(或列)中放置,可以使用此屬性設置換行

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap (默認): 不換行
  • wrap: 換行,第一行在上方
  • wrap-reverse: 換行,第一行在下方

flex-flow

它是 flex-direction 和 flex-wrap 屬性的縮寫.

flex-flow: <'flex-direction'> || <'flex-wrap'>

默認是: flex-flow: row nowrap

justify-content

justify-content.svg

定義子元素在主軸上的對齊方式

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
  • flex-start (默認): 左對齊,以主軸的起點對齊
  • flex-end: 右對齊,以主軸的終點對齊
  • center: 居中,以主軸的中點對齊
  • space-between: 兩端對齊,子元素間隔相等
  • space-around: 子元素兩側的間隔相等,因此,元素之間的間隔正好是與邊框間隔的兩倍
  • space-evenly: 子元素分佈排列,並且兩個元素的間隔與到邊框的間隔相等

align-items

align-items.svg

定義子元素在交叉軸上如何對齊

.container {
  align-items: stretch | flex-start | flex-end | center | baseline;
}
  • stretch (默認值): 如果子元素沒有指定高度或設爲 auto,將會拉伸佔滿容器的高度
  • flex-start: 以交叉軸的起點對齊
  • flex-end: 以交叉軸的終點對齊
  • center: 以交叉軸的中點對齊
  • baseline: 以子元素的第一行文字的基線對齊

align-content

align-content.png

定義容器內部多行元素的行對齊方式,類似於 justify-content 定義主軸內元素的對齊方式

注意: 當只有一行元素時,此屬性不生效

.container {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
  • stretch (默認值):每行拉伸佔滿整個交叉軸
  • flex-start:以交叉軸的起點對齊
  • flex-end:以交叉軸的終點對齊
  • center:以交叉軸的中點對齊
  • space-between:在交叉軸上兩端對齊,每行間隔相等
  • space-around:每行兩側的間隔相等,因此,行間隔正好是與邊框間隔的兩倍

Flex Items

Flex 容器內部的子元素也有 6 個屬性,分別是:

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

order

order.png

默認情況下,元素按原始順序排列,但是該屬性可以控制元素在 Flex 容器中的顯示順序,數值越小,越靠前,默認爲 0。

.item {
  order: <integer>; /* default is 0 */
}

flex-grow

flex-grow.png

定義元素在必要時擴大的能力s,比如容器還有剩餘空間。默認爲 0,有空間也不擴大。

如果所有元素都設置爲 1,那麼會均攤容器剩餘的空間;如果其中一個元素值爲 2,那麼它佔的剩餘空間是其他元素的兩倍(至少儘量會這樣做)。

注意: 負值無效。

.item {
  flex-grow: <number>; /* default 0 */
}

flex-shrink

定義元素在必要時縮小的能力默認爲 1,即如果空間不足,該元素將會縮小。

相對的,如果所有元素此屬性值都爲 1,空間不足時會等比例縮小;如果有一個元素值爲 0,其他爲 1,空間不足時,前者不縮小。

注意: 負值無效。

.item {
  flex-shrink: <number>; /* default 1 */
}

flex-basis

定義在分配容器剩餘空間之前,如何判斷子元素的大小,瀏覽器根據此屬性計算主軸剩餘空間的大小。

值可設爲指定長度(如 20%, 5rem)或關鍵字(auto)。默認爲 auto,元素的大小依據 main size(主尺寸),如果 main size 爲 auto,則使用元素內容的最大長度。

.item {
  flex-basis: <length> | auto; /* default auto */
}

子元素在彈性擴大時, flex-basis 的不同可能會造成不一樣的結果,下圖分別是"絕對"(從0開始算起)彈性和"相對"(從元素內容長度開始算起)彈性的差異結果。

rel-vs-abs-flex.svg

其中三個子元素 flex-grow 的值爲 1:1:2:

  • 如果是 flex-basis:0,瀏覽器會認爲子元素大小爲 0,剩餘空間就是整個容器空間,那麼就會把整個容器空間分配成 1:1:2 的比例
  • 如果是 flex-basis:auto,瀏覽器會認爲子元素大小就是 width 值,計算出剩餘空間,按 1:1:2 的比例分配給這個三個元素

由於瀏覽器計算主軸剩餘空間的大小不同,所以導致元素彈性結果的不同。

flex

該屬性是 flex-grow, flex-shrinkflex-basis 的簡寫,其中第二個和第三個參數( flex-shrink 和 flex-basis )是可選的.

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

默認是 flex: 0 1 auto, 建議優先使用此屬性,它有兩個簡便使用的關鍵字: auto(1 1 auto)none(0 0 auto).

align-self

align-self.png

允許元素覆蓋默認的或是使用 align-items 指定的對齊方式。

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

除了 auto, 其他屬性值都與 align-items 一致。

注意: float, clear 和 vertical-align 對 flex 容器內的元素不生效。

瀏覽器支持

flex-caniuse.png

其中:

  • 紅色 - 表示版本不支持
  • 黃綠色 - 表示帶前綴部分支持
  • 綠色 - 表示版本支持

最後回到題目的問題,常用的垂直居中,只需將 flex 容器的 align-items 和 justify-content 屬性值設爲 center 即可。

參考: A Complete Guide to Flexbox

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章