[譯] 選擇 Grid 仍是 Flex?

一個最近由 Chris Coyier 發起的的 推特話題 使我開始思考人們一般在什麼狀況下使用 CSS Grid 佈局仍是 Flexbox 佈局:css

對於已經理解了 CSS grid 和 flexbox 的大家來講,最喜歡的描述兩者之間差別的方法是什麼?前端

— Chris Coyier (@chriscoyier) January 25, 2019android

天然地一些最有見地的回覆來自於 Rachel Andrew 和 Jen Simmons:ios

Flexbox 是一種一維佈局。一行或者一列。Grid 是一種二維佈局。多行和多列。git

— Rachel Andrew (@rachelandrew) January 25, 2019github

Grid 創造了實際的列和行。內容會按你要求的一個接一個地排列整齊。Flexbox 則不會。不止是在二維(最顯而易見的),一樣也在一維條件下,Flexbox 並不適用於當今咱們一直使用它的大部份內容。算法

— Jen Simmons (@jensimmons) January 26, 2019後端

然而,只是單單閱讀推文並不會告訴咱們始末。這篇文章旨在告訴讀者二者的適用場景,以及在哪一種狀況下只能選擇使用其中一個。瀏覽器

當瀏覽話題下面的回覆時,我發現至關大數量的人只在頁面級的佈局中使用Grid,其餘狀況下直接使用 flexbox。若是你把這個當成一條準則,那麼你在嚴重地限制本身使用 Grid 的強大的功能。我特別建議:把每一個設計獨立化,分析可選方案的可行性,不要對你使用的技術來作出主觀的猜測。當你選擇一種佈局方法時,先捫心自問一下下面的這些問題。bash

你須要作多少計算?

這是我對這個話題的發出的推文:

當我看起來彷佛須要 calc() 對佈局使用大量的計算時,Grid 是一個更好的選擇。

— Michelle Barker (@mbarker_84) January 26, 2019

一般地,若是你不得不大量的使用 calc() 來獲得精確地位置與尺寸(例如考慮到間隔的狀況),那麼一般是值得去考慮一下使用 Grid 的,由於 fr 單位會幫咱們作繁重的適配,它會讓你不那麼頭痛。雖然做爲通常準則這很不錯,但也並非適用於全部的場景。這是一些你可能會用到 Grid 的場景,即便你的佈局並不須要大量的 calc()。一個例子是一個固定寬度的二維佈局,每一個網格軌道是 200px 寬 - 你不須要 calc() 來告訴你網格軌道應該是多寬,但你可能仍然想要 Grid 的表現行爲。一樣,有些你須要計算的狀況下也會使用 flexbox,所以這隻能做爲一個指南。

一維仍是二維?

Grid 和 flexbox 的一個很大的差別是 Grid 容許咱們在二維空間(多行多列)控制元素的位置,flexbox 則不行。再強調一次,那並不意味着你永遠不能在一維佈局中使用 Grid。我常常在我須要準確地在一維空間控制元素的尺寸和位置時選擇使用 Grid。就像在這個示例和隨附的文章中:

CodePen 上查看 Michelle Barker (@michellebarker) 寫的 帶有變量和媒體查詢的 CSS Grid 組件

你想要如何表現元素?

Grid 一般在你須要控制二維空間的佈局時是一個正確的選擇。但它不意味着對任何狀況來講都是一個更好的選擇。Grid 給你帶來的網格軌道(多行和多列),網格單元以及網格區域(多個網格單元組成的組)而且元素必須被放置在這些網格單元或者 Grid 區域。咱們可使用 Grid 或 flexbox 進行佈局,不過 Grid 佈局相較起來更加簡單明瞭。

假設咱們有這樣的佈局:

咱們有一個由九個等寬的元素組成的網格,從上到下排成三排,每一個元素之間有 20px 的間隙:

.grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	grid-auto-rows: 200px;
	/* 假設咱們想要咱們的行都是一個固定的高度 - 若是咱們想要高度響應地根據內容變化,能夠保留爲默認的 `auto` */
	gap: 20px;
}
複製代碼

元素以後就被自動放置,不須要咱們再作其餘的事情了。若是咱們真的想要它變得很是靈巧,咱們可使用 Grid 的 auto-fit()minmax() 方法來給咱們一個不須要媒體查詢的徹底響應式的佈局 - 嘗試調整此示例的大小,看看會發生什麼。

CodePen 上查看 Michelle Barker (@michellebarker) 的 Grid 自適應例子

我推薦觀看 Heydon Pickering 的視頻 算法佈局 來做爲一個對這個技術的概述等。

相反地,若是咱們想要使用 flexbox 建立這個佈局,咱們可能要設置實際的元素和網格容器的樣式:

.grid {
	display: flex;
	flex-wrap: wrap;
	margin: -10px;
	width: calc(100% + 20px);
}

.item {
	width: calc((100% / 3) - 20px);
	flex: 0 0 auto;
	margin: 0 10px 20px 10px;
}
複製代碼

咱們須要在網格容器上使用負 margin 來抵消這一事實 —— 內部元素的總的寬度可能要比容器更大,所以它會被換行到下一行。咱們也沒有了開箱即用的響應式行爲而且極可能須要使用媒體查詢。

CodePen 上查看 Michelle Barker (@michellebarker) 的 Flexbox 佈局示例

使用 flexbox 能夠經過幾種不一樣的方式實現相同的佈局,但他們都讓我感受有點複雜 - 它們原本就是那麼複雜。咱們將 flexbox 用於並非它真正被設計出來要作的事 — 但並不意味着它老是錯誤的選擇。

許多現代 CSS 框架對此佈局使用此方法的一些變體。做爲旁註,你若你真的要繼續走這條路,我由衷地向你推薦 Susy,它能夠幫你處理大量的計算。

因此,什麼是更好的選擇 — Grid 仍是 flexbox?彷佛 Grid 有一些明顯的優點,但爲了回答這個問題,咱們須要考慮當咱們有超過 9 個可是少於 12 個元素(下一個容許他們填充一行的多個元素)時會發生什麼。咱們想要新元素就像咱們已經看到的同樣乾脆直接放置在下一行的開始?又或是咱們想要它表現的不同?也許下一行就只有一個元素,咱們但願它佔用行全部的可用空間,就像下面的實例A。或者若是有兩個元素,那麼咱們但願它們居中,就像下面的示例 B。

使用 Grid 佈局和自動放置,咱們只能選擇將最後一項放在左側的單元格中,就像前面的例子所示 — 假設 direction 的值未設置爲 rtl(在這種狀況下元素會被按從右到左的順序放置,最後一項會放置在右側的單元格)。

CodePen 上查看 Michelle Barker (@michellebarker) 的 Flexbox 佈局示例

因此不管你爲上面的佈局選擇 Grid 或者 flexbox,實際上均可歸結爲你但願你的網格元素的響應變化 - 而且可以針對不一樣的狀況有不一樣的效果。

你想要用 Grid 替代 flexbox 嗎?

當我演講時,我常常被問到什麼時候應該使用 flexbox 而不是 Grid,以及咱們是否還須要 flexbox。在以前的例子裏咱們已經知道,Grid 不是 flexbox 的替代品。他們二者能夠很是愉快的共存,而且知道什麼時候使用它們能夠爲你的佈局提供更多的動力。

在上面的組件中,咱們須要控制文本、圖片以及橫走座標軸上的標題的位置,並控制它們如何在必定程度上相互交互。滿意的實現這個效果的方法只能是使用 Grid。

但我絕對會用 flexbox 來構建一個桌面導航菜單:

CodePen 上查看Michelle Barker (@michellebarker) 的Flexbox 導航

這裏我只想控制單維度的流,而且我想要元素是響應式 - 這也是 flexbox 作的至關出色的地方。使用 flexbox 咱們能夠選擇這些元素是否換行,並在全部項目沒法顯示在一行的狀況下容許他們優雅地換行。

怎樣適配不支持 Grid 的瀏覽器?

若是咱們使用 Grid,另外一個咱們須要考慮的問題是瀏覽器是否支持以及咱們想要在不支持的瀏覽器(IE11 及如下版本)上讓咱們的佈局如何展現:

.grid {
	display: flex;
	flex-wrap: wrap;
	/* 其他的後備佈局代碼 */
}

@supports (display: grid) {
	.grid {
		display: grid;
		/* 其他的 Grid 佈局代碼 */
	}
}
複製代碼

然而,若是你發現你本身花費數小時的時間來試圖爲不支持 Grid 的瀏覽器複製徹底相同的佈局,那麼可能一開始就不應 Grid。Grid 的好處是它能夠作一些 flexbox 單獨作不到的事情。

咱們在這裏討論了一些很是簡單,常見的佈局的例子和如何使用 Grid 和 flexbox 來實現它們。若是想要看一些其餘的複雜的例子,能夠看一下這篇博客中的其餘文章,或者繼續關注我將來的更多帖子。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索