2024年CSS終於實現垂直置中
在2024年,align-content終於可以在塊級佈局中運作了。只需一個CSS屬性就能實現垂直置中,而不需使用Flexbox或Grid。
1 | <div style="align-content: center; height: 100px;"> |
支援情況:
Chrome: 123 | Firefox: 125 | Safari: 17.4
可以看到只支援比較新的瀏覽器版本,所以使用上還是得考慮一下,總的來說,雖然我們會很興奮地看到新的 CSS 特性出現,但在實際開發中,我們需要平衡新特性的使用和對舊版瀏覽器的支援。通常,我們會採用漸進式增強的策略,確保基本功能在所有環境中都能正常運作,同時為支援新特性的瀏覽器提供更好的體驗。。
有什麼新變化?
CSS對齊的現況是需要切換到flexbox或grid佈局,因為align-content在預設佈局(flow)中不起作用。在2024年,瀏覽器實作了流式佈局的align-content。這帶來一些好處:
- 你不需要使用flexbox或grid,只需要一個CSS屬性就能實現對齊。
- 因此,內容不需要包裝在一個div中。
1 | <!-- 可以運作 --> |
1 | <!-- 失敗! --> |
1 | <!-- 使用內容包裝器可以運作 --> |
1 | <!-- 不需要內容包裝器就可以運作 --> |
經過幾十年的進步,CSS終於有了一個單一屬性來控制垂直對齊,這真是太棒了!
垂直置中 - 歷史回顧
瀏覽器很有趣,像對齊這樣的基本需求在很長一段時間內都沒有簡單的解決方案。以下是如何置中內容:
以下是在瀏覽器中如何垂直置中(水平置中是另一個話題):
方法1:表格單元格
有4種主要佈局:flow(預設)、table、flexbox、grid。如何對齊內容取決於容器的佈局。flexbox和grid是後來才加入的,所以table是最早的選擇。
1 | <div style="display: table;"> |
可以僅透過CSS召喚出一個表格,但需要這樣一個間接方法實在是一種恥辱。
方法2:絕對定位
1 | <div style="position: relative;"> |
這種方法使用絕對定位來繞過佈局,因為流式佈局無法幫助我們:
- 用
position: relative標記參考容器。 - 用
position: absolute; top: 50%將內容邊緣放在中心。 - 用
transform: translateY(-50%)將內容中心偏移到邊緣。
此方法的缺點有:
- 複雜性:這個方法需要多個 CSS 屬性組合,不夠直觀。
- 破壞文檔流:使用絕對定位會將元素從正常文檔流中移除,可能導致佈局問題。
- 需要額外的包裝元素:這個方法通常需要一個額外的容器元素。
- 不靈活:在某些情況下,這種方法可能不適用,特別是當容器高度不固定時。
- 性能考慮:使用 transform 可能在某些情況下引起性能問題。
- 不符合語義:這種方法使用了與內容語義無關的 CSS 技巧來實現佈局。
不過這個方法還是很多開發者在使用,因為
- 廣泛支援:這個方法在絕大多數瀏覽器中都能正常工作,包括較舊的版本。
- 可靠性:一旦掌握,這個方法在大多數情況下都能可靠地工作。
- 靈活性:可以輕易調整以適應不同的情況,如水平置中。
- 習慣:許多開發者已經習慣了這種方法,並能快速實現。
- 相容性好:不依賴於新的 CSS 特性,因此在各種環境中都能使用。
- 問題解決:儘管不完美,但它解決了一個常見的佈局問題。
方法3:行內內容
雖然流式佈局不能幫助內容對齊,但它允許在行內進行垂直對齊。那麼為什麼不讓一行和容器一樣高呢?
1 | <div class="container"> |
1 | .container::before { |
這有一些缺陷:除了犧牲一個偽元素外,開頭還有一個零寬度的"支柱"字元可能會搞亂東西。
方法4:單行flexbox
flexbox在Web出現20年後才廣泛可用。它有兩種模式:單行和多行。在單行模式(預設)下,該行填滿垂直空間,align-items在行內對齊內容。
1 | <div style="display: flex; align-items: center;"> |
或者,讓行變成列,用justify-content對齊項目。
1 | <div style="display: flex; flex-flow: column; justify-content: center;"> |
方法5:多行flexbox
在多行flexbox中,行不再填滿垂直空間,所以可以用align-content對齊只有1個項目的行。
1 | <div style="display: flex; flex-flow: row wrap; align-content: center;"> |
方法6:網格內容
網格出現得更晚。對齊變得更簡單。
1 | <div style="display: grid; align-content: center;"> |
方法7:網格單元格
注意與前一種方法的細微差別:
align-content將單元格相對於容器置中。align-items將內容相對於單元格置中,而單元格會拉伸以適應容器。
1 | <div style="display: grid; align-items: center;"> |
似乎有很多方法可以做同樣的事情。
方法8:自動外邊距
在流式佈局中,margin:auto可以水平置中,但不能垂直置中。flexbox和Grid沒有這個問題。
1 | <div style="display: grid;"> |
不過,我還是很困惑為什麼要設計邊距來控制對齊。
方法9:2024年的這篇文章
為什麼瀏覽器一開始就不加入這個功能呢?
1 | <div style="align-content: center;"> |
方法1中的表格單元格,像這種方法一樣,也不需要內容包裝器(儘管它需要一個表格包裝器)。我們又回到了起點!
不過使用上要看瀏覽器是否支援,可以使用以下策略:
- 使用特性檢測:
1
2
3
4
5if ('alignContent' in document.documentElement.style) {
// 使用新的 align-content 方法
} else {
// 使用備用方法
} - 使用 CSS @supports:
1
2
3
4
5
6
7
8
9
@supports (align-content: center) {
.container {
align-content: center;
}
}
@supports not (align-content: center) {
/* 當樣式不被瀏覽器所支援就套用此處的樣式 */
}總結
以下是所有垂直置中方法
1 | <p>Various methods for vertical centering. Yellow is container and green is content wrapper. Note that the first and last methods do not require a content wrapper.</p> |
實現二維對齊
有沒有一個水平對齊的單一屬性?align-content的對應屬性是什麼?讓我們看看各種對齊屬性:
| flow | flexbox | grid | |
|---|---|---|---|
align-content |
block軸 | 交叉軸(行) | block軸(網格) |
justify-content |
無效果 | 主軸 | inline軸(網格) |
align-items |
無效果 | 交叉軸(項目) | block軸(單元格) |
justify-items |
無效果 | 無效果 | inline軸(單元格) |
表:不同佈局中的對齊屬性
背景:CSS軸術語
block軸通常是垂直的,inline軸是水平的。需要這些術語是因為垂直writing-mode是存在的,所以block軸和inline軸是相對於文字方向的。這類似於主軸和交叉軸是相對於flexbox項目方向的。
結論: "items"用於可以單獨對齊的內容。在主軸上,flex項目不能單獨對齊,所以是"content"。
