如何在 CSS 中對齊事物
已發表: 2022-03-10今天,我們有很多方法可以在 CSS 中對齊事物,但使用哪種方法並不總是一個顯而易見的決定。 然而,知道什麼是可用的意味著如果你遇到一個特定的對齊問題,你總是可以嘗試一些策略。
在本文中,我將介紹不同的對齊方法。 我不會為每個人提供全面的指南,而是解釋人們的一些癥結,並指出更完整的屬性和值參考。 與大多數 CSS 一樣,您可以通過了解有關方法行為方式的基本知識來走很長的路,然後需要一個地方去查找有關如何實現所需精確佈局的更精細的細節。
對齊文本和內聯元素
當我們在頁面上有一些文本和其他內聯元素時,每一行內容都被視為一個行框。 屬性text-align
將對齊頁面上的內容,例如,如果您希望文本居中或對齊。 但是,有時您可能希望將該行框中的內容與其他內容對齊,例如,如果您有一個圖標顯示在文本旁邊,或者不同大小的文本。
在下面的示例中,我有一些帶有較大內聯圖像的文本。 我在圖像上使用vertical-align: middle
將文本與圖像的中間對齊。
line-height
屬性和對齊方式
記住line-height
屬性會改變 line-box 的大小,因此可以改變你的對齊方式。 以下示例使用 150px 的大 line-height 值,並且我已將圖像對齊到top
。 圖像與行框的頂部對齊,而不是文本的頂部,刪除該行高或使其小於圖像的大小,圖像和文本將在文本的頂部對齊。
事實證明, line-height
和文本的大小確實相當複雜,我不打算在本文中深入探討這個兔子洞。 如果您嘗試精確對齊內聯元素並想真正了解發生了什麼,我建議您閱讀“Deep Dive CSS: Font Metrics, line-height
and vertical-align
”。
什麼時候可以使用vertical-align
屬性?
如果要對齊任何內聯元素, vertical-align
屬性很有用。 這包括帶有display: inline-block
元素。 表格單元格的內容也可以使用vertical-align
屬性對齊。
vertical-align
屬性對彈性或網格項目沒有影響,因此如果用作後備策略的一部分,它將在父元素變成網格或彈性容器的那一刻停止應用。 例如,在下一支筆中,我有一組用display: inline-block
佈局的項目,這意味著即使瀏覽器沒有 Flexbox,我也可以對齊項目:
在下一篇文章中,我將inline-block
視為 Flex 佈局的後備。 對齊屬性不再適用,我可以添加align-items
來對齊 Flexbox 中的項目。 您可以看出 Flexbox 方法正在發揮作用,因為使用display: inline-block
時您將獲得的項目之間的間隙消失了。
vertical-align
在表格單元格上起作用的事實是使用display: table-cell
使項目垂直居中的技巧起作用的原因。
現在我們確實有更好的方法來對齊 CSS 中的框(我們將在下一節中看到),我們不需要在除了 inline 和 text 元素之外的地方使用vertical-align
和text-align
屬性他們被設計的。 但是,它們在這些文本和內聯格式中使用仍然完全有效,因此請記住,如果您嘗試內聯對齊某些內容,則需要使用這些屬性而不是 Box Alignment 屬性。
框對齊
Box Alignment Specification 處理我們如何對齊其他所有內容。 該規範詳細說明了以下對齊屬性:
-
justify-content
-
align-content
-
justify-self
-
align-self
-
justify-items
-
align-items
您可能已經將這些屬性視為 Flexbox 規範或 Grid 的一部分。 屬性的歷史是它們起源於 Flexbox 的一部分,並且仍然存在於 Level 1 規範中; 然而,當它們變得更普遍有用時,它們被轉移到自己的規範中。 我們現在也在網格佈局中使用它們,並且它們也被指定用於其他佈局方法,儘管當前的瀏覽器支持意味著你還不能使用它們。
因此,下次互聯網上有人告訴你垂直對齊是 CSS 中最難的部分時,你可以告訴他們(這甚至適合推文):
.container { display: flex; align-items: center; justify-content: center; }
將來,一旦為塊佈局實現了 Box Alignment 屬性,我們甚至可以省去display: flex
。 然而,目前,讓你想要的東西的父對象居中一個 flex 容器是水平和垂直對齊的方法。
兩種對齊方式
對齊 flex 和 grid 項目時,您有兩種可能的對齊方式:
- 您在網格或彈性容器中有空閒空間(一旦項目或軌道佈置好)。
- 您還可以將項目本身放在放置它的網格區域內,或者在 flex 容器內的交叉軸上。
我在上面展示了一組屬性,對齊屬性可以被認為是兩組。 處理空閒空間分配的那些,以及對齊項目本身的那些。
處理備用空間: align-content
和justify-content
以-content
結尾的屬性是關於空間分配的,因此當您選擇使用align-content
或justify-content
時,您是在網格軌道或彈性項目之間分配可用空間。 它們本身不會改變 flex 或 grid 項目的大小; 他們移動它們是因為它們改變了空閒空間的去向。
下面,我有一個 flex 示例和一個 grid 示例。 兩者都有一個大於顯示彈性項目或網格軌道所需的容器,因此我可以使用align-content
和justify-content
來分配該空間。
移動項目: justify-self
, align-self
, justify-items
和align-items
然後我們align-self
和justify-self
應用於單個 flex 或 grid 項目; 您還可以在容器上使用align-items
和justify-items
來一次設置所有屬性。 這些屬性處理實際的彈性或網格項目,即在網格區域或彈性線內移動內容。
- 網格佈局
您可以獲得這兩個屬性,因為您可以在塊和內聯軸上移動項目,因為我們定義了它所在的網格區域。 - 彈性佈局
您只能在交叉軸上對齊,因為主軸僅由空間分佈控制。 因此,如果您的項目是一排,您可以使用align-self
在 flex line 內上下移動它們,使它們相互對齊。
在下面的示例中,我有一個 flex 和一個網格容器,並在 Flexbox 中使用align-items
和align-self
來在交叉軸上上下移動項目。 如果您使用 Firefox,並使用 Firefox Flexbox Inspector 檢查元素,您可以看到 flex 容器的大小以及項目如何在其中垂直移動。
在網格中,我可以使用所有四個屬性在網格區域內移動項目。 再一次,Firefox DevTools Grid Inspector 在玩對齊時會很有用。 疊加網格線後,您可以看到內容正在移動的區域:
使用 CodePen 演示中的值來查看如何在每種佈局方法中移動內容:
被align
和justify
弄糊塗了
人們在 Grid 和 Flexbox 中記住對齊屬性時被引用的問題之一是,沒有人能記住是對齊還是對齊。 哪個方向是哪個?
對於網格佈局,您需要知道您是在塊方向還是內聯方向上對齊。 塊方向是在您的頁面上佈置的方向塊(在您的寫作模式下),即垂直的英語。 內聯方向是句子運行的方向(因此對於水平從左到右的英語)。
要在塊方向上對齊事物,您將使用以align-
開頭的屬性。 如果網格容器中有空閒空間,您可以使用align-content
在網格軌道之間分配空間,並使用align-items
或align-self
在已放置的網格區域內移動項目。
下面的示例有兩個網格佈局。 一個有writing-mode: horizontal-tb
(這是英語的默認設置)和另一個writing-mode: vertical-rl
。 這是他們之間唯一的區別。 您可以看到我應用的對齊屬性在兩種模式下在塊軸上的工作方式完全相同。
要將事物沿內聯方向對齊,請使用以justify-
開頭的屬性。 使用justify-content
在網格軌道之間分配空間,並使用justify-items
或justify-self
以沿內聯方向對齊網格區域內的項目。
再一次,我有兩個網格佈局示例,因此您可以看到內聯始終是內聯的——無論您使用哪種書寫模式。
Flexbox 有點棘手,因為我們有一個可以更改為row
或column
的主軸。 所以,讓我們首先考慮一下主軸。 它使用flex-direction
屬性設置。 此屬性的初始(或默認)值是row
,它將在當前使用的書寫模式下將 flex 項目排列為一行 - 這就是為什麼在使用英語工作時,當我們創建一個彈性容器。 然後,您可以將主軸更改為flex-direction: column
並且項目將被佈置為列,這意味著它們在該書寫模式下以塊方向佈置。
由於我們可以進行軸切換,Flexbox 中最重要的因素是詢問“哪個軸是我的主軸?” 一旦你知道了,那麼為了對齊(在你的主軸上)你只需使用justify-content
。 您的主軸是行還是列都沒有關係。 您可以使用justify-content
控制彈性項目之間的空間。
在交叉軸上,您可以使用align-items
對齊彈性容器內的項目或多行彈性容器中的彈性線。 如果你有一個使用flex-wrap: wrap
的多行容器並且在該容器中有空間,你可以使用align-content
在交叉軸上分配空間。
在下面的示例中,我們同時使用顯示為行和列的 flex 容器:
當justify-content
或align-content
不起作用時
Grid 和 Flexbox 中的justify-content
和align-content
屬性是關於分配額外空間的。 所以要檢查的是你有額外的空間。
這是一個 Flex 示例:我設置了flex-direction: row
並且我有三個項目。 它們不會佔用 flex 容器中的所有空間,所以我在主軸上有空閒空間, justify-content
的初始值是flex-start
,所以我的項目都在開始時排成一行,額外的空間是在最後。 我正在使用 Firefox Flex Inspector 突出顯示空間。
如果我將 flex-direction 更改為space-between
,那麼現在將在項目之間分配額外的空間:
如果我現在向我的項目添加更多內容,使它們變得更大並且不再有任何額外的空間,那麼justify-content
什麼也不做——只是因為沒有空間可以分發。
我被問到的一個常見問題是為什麼當flex-direction
為column
時justify-content
不起作用。 這一般是因為沒有空間可以分發。 如果您採用上面的示例並將其設為flex-direction: column
,則項目將顯示為一列,但項目下方不會像您執行flex-direction: row
時那樣有額外的空間。 這是因為當你使用display: flex
創建一個 Flex 容器時,你有一個塊級的 flex 容器; 這將佔用內聯方向上的所有可能空間。 在 CSS 中,事物不會在塊方向上拉伸,因此沒有多餘的空間。
為容器添加一個高度——只要它超過顯示項目所需的高度——你就有了額外的空間,因此justify-content
將在你的列上工作。
為什麼 Flexbox 中沒有justify-self
?
網格佈局實現了兩個軸的所有屬性,因為在網格佈局中我們總是有兩個軸要處理。 我們創建軌道(這可能會在任一維度的網格容器中留下額外的空間),因此我們可以使用align-content
或justify-content
分配該空間。 我們也有 Grid Areas,那個區域的元素可能不會佔滿區域的全部空間,所以我們可以使用align-self
或者justify-self
來移動區域周圍的內容(或者align-items
, justify-items
更改所有項目的對齊方式)。
Flexbox 不像 Grid 佈局那樣有軌道。 在主軸上,我們所要做的只是項目之間的空間分佈。 沒有放置彈性項目的軌道的概念。 所以沒有創建用於移動項目的區域。這就是為什麼在 Flexbox 的主軸上沒有justify-self
屬性。
但是,有時您確實希望能夠以不同的方式對齊一個項目或一組項目的一部分。 一種常見的模式是拆分導航欄,其中一個項目從組中分離出來。 在這種情況下,規范建議使用自動邊距。
自動邊距將佔據應用方向上的所有空間,這就是為什麼我們可以使用 auto 的左右邊距使塊居中(例如我們的主頁佈局)。 兩邊都有自動邊距,每個邊距都試圖佔據所有空間,因此將塊推到中間。 使用我們的彈性項目行,我們可以將margin-left: auto
添加到我們希望發生拆分的項目上,只要彈性容器中有可用空間,您就會得到拆分。 這與 Flexbox 配合得很好,因為一旦沒有可用空間,這些項目就會像常規的彈性項目一樣表現。
Flexbox 和微組件
我認為經常被忽視的一件事是 Flexbox 對於做微小的佈局工作有多麼有用,你可能認為使用vertical-align
是要走的路。 我經常使用 Flexbox 來整齊對齊小圖案; 例如,對齊文本旁邊的圖標,基線對齊兩個不同字體大小的東西,或者使表單域和按鈕正確排列。 如果您正在努力讓一些東西與vertical-align
很好地對齊,那麼也許可以嘗試使用 Flexbox 來完成這項工作。 請記住,如果需要,您還可以使用display: inline-flex
創建一個內聯 flex 容器。
沒有理由不使用 Flexbox,甚至 Grid 來完成微小的佈局工作。 它們不僅適用於大塊佈局。 嘗試你可以使用的不同的東西,看看什麼最有效。
人們通常非常渴望知道做事的正確或錯誤方式是什麼。 在現實中,往往沒有對錯之分; 您的模式中的微小差異可能意味著 Flexbox 工作得最好的差異,否則您將使用vertical-align
。
包起來
最後,我快速總結了對齊的基礎知識。 如果你記住了這幾條規則,你應該能夠用 CSS 對齊大多數東西:
- 您是對齊文本還是內聯元素? 如果是這樣,您需要使用
text-align
、vertical-align
和line-height
。 - 您是否有一個或多個項目要在頁面或容器的中心對齊? 如果是這樣,將容器設置為 flex 容器,然後設置
align-items: center
和justify-content: center
。 - 對於網格佈局,以
align-
開頭的屬性在塊方向上起作用; 以justify-
開頭的那些在 inline 方向上工作。 - 對於 Flex 佈局,以
align-
開頭的屬性在 Cross Axis 上起作用; 以justify-
開頭的那些在主軸上工作。 -
justify-content
和align-content
屬性分配額外的空間。 如果您的 flex 或 grid 容器中沒有多餘的空間,它們將什麼也不做。 - 如果您認為在 Flexbox 中需要
justify-self
,那麼使用自動邊距可能會為您提供所需的模式。 - 您可以將 Grid 和 Flexbox 與對齊屬性一起用於小型佈局作業和主要組件 — 實驗!
有關對齊的更多信息,請參閱以下資源:
- CSS 框對齊(MDN 網絡文檔)
- 關於 Flexbox 對齊你需要知道的一切
- 框對齊備忘單