[譯] Flexbox 對齊全知道!

原文連接:Everything You Need To Know About Alignment In Flexbox, by Rachel Andrewcss

本系列的第一篇文章 中,我解釋了當在元素上聲明 display: flex 的時候,發生了什麼。這一次我將帶領你們瀏覽一下對齊屬性(alignment properties),看看它們是如何在 Flexbox 中起做用的。若是你曾困惑不知道該使用 align-* 屬性仍是 justify-* 屬性的話,我但願本文可以幫你解決這個困惑。設計模式

Flexbox 對齊屬性簡史

在整個 CSS 佈局歷史中,如何能自如地在兩個軸上對齊元素多是 Web 設計領域的最讓人頭大的問題了。所以第一次看見 Flexbox 中對齊項目的功能時,是很是使人興奮的。好比,下面兩行 CSS 便能輕鬆作到居中對齊:安全

See the Pen Smashing Flexbox Series 2: center an item by Rachel Andrew佈局

你可能認爲這些屬性僅是做爲 Flexbox 佈局中的對齊屬性使用的,事實上不是,這些屬性如今都定義在了 Box Alignment 規範 中。這個規範描述了這些對齊屬性是如何在不一樣的佈局上下文(layout contexts)中起做用的。也就是說,咱們能夠在 CSS 網格(Grid)中使用在彈性佈局中用到的這些對齊屬性——固然,將來可能還會有其餘的佈局上下文出現。所以,將來 Flexbox 中新的對齊功能將會在 Box Alignment 規範中定義,而不是在 Flexbox 規範中。post

屬性

許多人跟我說在使用 Flexbox 過程當中,很容易被「這裏該使用 align- 屬性仍是 justify 屬性?」的問題搞懵圈。這裏告訴你一個簡單的記憶方法:flex

  • justify- 操做的是主軸(main axis)對齊,對齊方向與 flex-direction 方向一致。
  • align- 操做的是交叉軸(cross axis)對齊,對齊方向與 flex-direction 方向垂直。

這裏咱們使用的是「主軸」和「交叉軸」,而沒有說「水平方向」或「垂直方向」,是由於前者(兩根軸)的方向跟物理方向並非關聯的。flexbox

主軸對齊:justify-content

咱們從主軸對齊開始講起。在主軸上對齊,咱們使用的是 justify-content 屬性。這個屬性把全部的 Flex 項目當成一組,控制項目之間的空間分配。spa

justify-content 的初始值是 flex-start。這就是爲何,在聲明 display: flex 以後,全部的 Flex 項目都是在彈性線(flex line) 的起始處對齊的。當 flex-directionrow 且處於從左到右的語言環境的時候(好比英語),這個起始處就位於左邊。設計

Flex 項目在起始處對齊3d

須要注意的是,justify-content 僅在有剩餘空間可供分配的狀況下才起做用。若是在主軸上,Flex 項目分配完畢後,已無可供分配的剩餘空間,justify-content 不會起任何做用。

無空間可供分配

若是咱們給 justify-content 使用的是 flex-end,那麼全部項目都是在彈性線末尾對齊,剩餘空間位於頭部。

Flex 項目在末尾處對齊

剩餘空間的分配還有更多方式。好比,咱們能夠空間在 Flex 項目之間平均分配,須要用到 justify-content: space-between。這種狀況下,第一個和最後一個 Flex 項目會靠在容器邊緣,而後剩餘空間會在項目之間均等分配。

剩餘空間在項目之間平均分配

也可使用 ustify-content: space-around。這種狀況下,剩餘空間會在每一個項目的兩邊分配。

剩餘空間在每一個項目的兩邊分配

譯註:由於每一個項目兩邊都分到了同樣的空間。所以,項目間的間距會是項目與容器邊緣間距的兩倍。圖中的容器設置了 padding 值,所以看出的效果可能沒那麼明顯,在此告知你們。

Box Alignment 規範還爲 justify-content 屬性定義了一個新值 space-evenly ,它並未出如今 Flexbox 規範中。使用了這個值後,項目與容器之間、項目與項目之間的分配的空間大小是同樣的。

項目均勻分佈於容器內

下面的 demo 展現了在不一樣取值狀況下的項目分配:

See the Pen Smashing Flexbox Series 2: justify-content with flex-direction: row by Rachel Andrew

flex-direction 取值 column 的時候,這些值的做用效果是同樣的。固然了,除非你給 Flex 容器一個高度或者容器自己是 block-size 的,不然是沒有額外空間可供非配的。請看下面的 demo:

See the Pen Smashing Flexbox Series 2: justify-content with flex-direction: column by Rachel Andrew

交叉軸對齊:align-content

若是 Flex 容器使用了 flex-wrap: wrap,咱們就能獲得多行(multiple flex lines) 顯示的 Flex 項目,align-content 就是處理在交叉軸上行之間的剩餘空間分配。固然,前提是在交叉軸上存在剩餘空間可供分配。在下面的例子中,交叉軸以列的形式在塊方向(block direction)上佈局,我把容器的高度設置爲 60vh 了,這比 Flex 項目所須要的空間要多,這樣咱們就有空間在垂直方向上進行分配了。

咱們可使用下圖裏列舉的值,佈局交叉軸上的對齊:

See the Pen Smashing Flexbox Series 2: align-content with flex-direction: row by Rachel Andrew

若是 flex-direction 取值 column,則 align-content 將按以下方式佈局:

See the Pen Smashing Flexbox Series 2: align-content with flex-direction: column by Rachel Andrew

相似於 justify-contentalign-content 是把多行當作一個組來分配剩餘空間的。

簡寫屬性:place-content

閱讀 Box Alignment 規範,發現有一個簡寫屬性 place-content,這個屬性是 justify-content 屬性和 align-content 屬性的簡寫形式。place-content 接收兩個值,第一個值指定 align-content,第二個值指定 justify-content;若是隻指定一個值的話,兩個屬性都設置爲這個值。所以:

.container {
    place-content: space-between stretch;
}
/* 等效於 */
.container {
    align-content: space-between;
    justify-content: stretch;
}

/* 若是是這樣使用的 */

.container {
    place-content: space-between;
}
/* 則等效於 */
.container {
    align-content: space-between;
    justify-content: space-between;
}
複製代碼

交叉軸對齊:align-items

咱們已經知道,能夠將一組 Flex 項目或將多行彈性線(flex lines)做爲組進行對齊。可是還有一個小小的需求,就是但願在交叉軸上以彼此關聯的方式對 Flex 項目作對齊。Flex 容器會有一個高度,這個高度多是由最高的那個 Flex 項目決定的。

容器的高度是由第三個項目的高度決定的

固然,也能夠直接給 Flex 容器一個高度:

直接在容器上定義了高度

其餘 Flex 項目之因此會伸展與最高項同樣的高度,是由於 align-items 屬性的初始值是 stretch 。項目在交叉軸上伸展,直到尺寸和 Flex 容器的尺寸同樣。

咱們要注意到 align-items 的做用點是哪裏。對於多行 Flex 容器,每一行都像是一個新的 Flex 容器,那一行裏最高的 Flex 項目將決定改行其餘項目的高度。

除了初始值 stretch,還可使用 flex-start,此屬性會讓 Flex 項目沿着容器的起點處對齊,不會伸展到與容器同樣的高度了。

Flex 項目沿着交叉軸的起點處對齊

flex-end 則讓 Flex 項目沿着交叉軸的終點處對齊。

Flex 項目沿着交叉軸的終點處對齊

若是使用的是 center,則全部項目的沿着中心對齊。

在交叉軸上居中對齊項目

還能夠基於基線對齊。與上面的基於項目中心線對齊不一樣,這是根據文本的基線對齊的:

基線對齊

能夠查看下圖,發現不一樣值產生的效果:

See the Pen Smashing Flexbox Series 2: align-items by Rachel Andrew

單個項目對齊:align-self

align-items 的意思是一次設置全部 Flex 項目的對齊方式。實際是把全部 Flex 項目的 align-self 屬性作了統一的設置。你也能夠在單個 Flex 項目上使用 align-self 屬性,指定在行(flex line)內與其它 Flex 項目不一樣的對齊方式。

在下例中,咱們在 Flex 容器上將 align-items 屬性設置爲 center,而且爲第一個和最後一個項目分別指定了單獨的對齊方式。

See the Pen Smashing Flexbox Series 2: align-self by Rachel Andrew

爲何沒有 justify-self?

譯註:

原文做者這裏的解釋有點牽強。詳細可參考 stackoverflow 上的回答:In CSS Flexbox, why are there no 「justify-items」 and 「justify-self」 properties?

總結下來的話,就是沒有必要,由於使用下面即將要說的 auto margin 方案就能解決。規範中也是介紹使用 auto margin 解決主軸上部分項目的個性化對齊問題的。

一個常見的問題是,如何在主軸對齊一個項目或者一組項目。爲何 Flexbox 主軸上沒有 -self 屬性?若是你知道 justify-contentalign-content 是用來分配剩餘空間的,那麼可能就能搞懂爲何沒有 self-alignment 屬性了。咱們把 Flex 項目當作一組,並對可用空間進行分配——在組的頭部或者尾部或者再項目之間。

咱們能夠思考下 justify-contentalign-content 屬性在 CSS Grid 佈局中的做用。這兩個屬性在 Grid 中是用來分配*網格軌跡之間(between grid tracks)*的間距的。它們把軌跡當作是一個組,這些屬性就是用來分配這些軌跡之間的間距的。因爲咱們同時在 Grid 和 Flexbox 中對一個組進行操做,所以咱們不能單獨針對一個項目來作一些不一樣的事情。然而,有一種方法能夠實現當您在主軸上請求 self 屬性時所要求的那種佈局,那就是使用 auto margin。

在主軸上使用 auto margin

若是你有過用 CSS 居中顯示一個塊元素的經驗(經過給內容頁設置左右 marginauto),你就已經理解 auto margin 實現居中的行爲。若是咱們設置了一個方向上的 margin: auto,那麼這個 margin 會盡量的佔據該方向的空間大小。在使用 margin 居中塊元素的例子中,咱們將左右 margin 都設置爲了 auto,它們每一個都儘量的爭奪空間,最終將塊元素推倒了中間的位置。

auto margin 在主軸對齊上一樣表現優秀,它能夠實現單個項目或者一組項目的對齊。下例中,我實現了一個常見的設計模式——我使用 Flexbox 實現了一個導航欄,項目顯示爲一行,使用了初始值 justify-content: start。我想讓最後一個項目顯示在彈性線(flex line)的末尾(固然,前提假設是這一行上有足夠的空間)。

我選中了這個項目,而且給了它 margin-left: auto。這就是說項目的左邊會佔據儘量多的空間,也就是說這個項目會被推倒了右邊。

See the Pen Smashing Flexbox Series 2: alignment with auto margins by Rachel Andrew

若是在主軸上使用了 auto margin,justify-content 就會失去效果,由於 auto margin 會佔據全部原本要給 justify-content 分配的空間。

回退對齊

每一個對齊方法都有一個詳細的回退對齊,這是在請求的對齊不能實現的狀況下發生的事。例如,若是在容器中只有一個項目,而且使用了 justify-content: space-between,那麼結果如何?答案是會使用回退對齊 flex-start,而後發現這個項目在 Flex 容器的起點處對齊了;對 justify-conrtent: space-around 的狀況,回退對齊是 center

當前規範中,咱們還沒法修改回退對齊,若是你想讓 space-between 的回退方案採用 center 而非 flex-start 的話,是作不到的。 規範中有一個 Note 提到將來的版本中可能會支持。

Safe 和 Unsafe 對齊

Box Alignment 規範最近新增了 Safe 和 Unsafe 對齊的概念,對應關鍵字 safeunsafe

下面的代碼中,最後一項對於 Flex 容器來講太寬了,且對齊方式不安全。Flex 容器位於頁面左側,當溢出超出頁面邊界時,發現這一項被切斷了。

.container {  
    display: flex;
    flex-direction: column;
    width: 100px;
    align-items: unsafe center;
}

.item:last-child {
    width: 200px;
}
複製代碼

不安全的對齊方式致使的對齊結果可能致使數據丟失

而安全對齊方式會避免數據丟失的出現,將溢出轉移到另外一邊。

.container {
    display: flex;
    flex-direction: column;
    width: 100px;
    align-items: safe center;
}

.item:last-child {
    width: 200px;
}
複製代碼

安全對齊避免數據丟失

See the Pen Smashing Flexbox Series 2: safe or unsafe alignment by Rachel Andrew

總結

對齊屬性起源於 Flexbox,可是如今位於獨立的規範中,並可用於其餘佈局上下文中。如下幾個關鍵事實將幫助你記住如何在 Flexbox 中使用它們:

  • justify- 主軸對齊,align- 交叉軸對齊;
  • 使用 align-contentjustify-content 屬性時須要有額外的剩餘空間;
  • align-contentjustify-content 屬性把 Flex 項目當作一組來處理。所以對這些屬性而言,沒有針對單個項目的 -self 對齊屬性。
  • 若是你但願在主軸上對齊一個項目,或者把部分項目做爲一組對齊的話,可使用 auto margin。
  • align-items 用於統一設置 Flex 項目上的 align-self 屬性。在 Flex 項目上使用 align-self 用於單獨設置此項目的對齊方式。

(完)

相關文章
相關標籤/搜索