1. 程式人生 > >震驚!很多人都不知道 CSS Grid 框架早就有了!

震驚!很多人都不知道 CSS Grid 框架早就有了!

![](https://img2020.cnblogs.com/blog/999445/202011/999445-20201108224642309-874784610.jpg) ## 前言 寫作本文起源於知乎的一個問題:【[CSS Grid 佈局那麼好,為什麼至今沒有人開發出基於 Grid 佈局的前端框架呢?](https://www.zhihu.com/question/397861009/answer/1283665997)】 這篇文章拖沓了兩個月,是因為真的不知道從哪裡說好。這個問題的所有回答幾乎都沒有切中問題的本質,而且對 CSS Grid 也有很深的誤解。另外這個問題的描述可能不太恰當,因為基於 CSS Grid 的框架已經有了。感興趣的朋友可以瞭解一下 [Flex-Layout](https://github.com/angular/flex-layout/wiki/Declarative-API-Overview),它是一個基於指令佈局的神器。大家不要被專案名誤導,雖然叫 `flex-layout`,其實有 `flex` 和 `grid` 兩種指令。 我覺得這個問題更恰當的描述應該是【為什麼沒有基於 Grid 佈局的純 CSS 前端框架呢】,基於 Float 和 Flex 的 CSS 佈局框架多如牛毛,但是一直沒看到基於 CSS Grid 的實現。我在寫 [Snack](https://github.com/snack-ui/snack) 的時候也曾考慮過在 v3 版本中整合 CSS Grid,但是後來發現有些不現實,下文詳述。據說 Bootstrap 也曾打算在 v5 版本整合 CSS Grid,但是目前來看依然沿用了 Flex 佈局。我個人覺得基於指令實現的 `flex-layout` 應該是整合 CSS Grid 的最佳方式。 本文打算從相反的角度聊一聊,假如要實現一個基於 CSS Grid 的佈局框架,我們會遇到哪些問題呢? ## 瀏覽器相容性 先說一下相容性,很多人總覺得 CSS Grid 的相容性不行。其實不然,下圖的統計資料能夠看出大部分瀏覽器對 CSS Grid 的支援還是不錯的,要知道 Flex 在 IE10 上面可以使用的屬性也非常有限。據統計目前 CSS Grid 使用率和 Flex 已經基本持平了。所以相容性並不能回答開篇提出的問題。 ![](https://img2020.cnblogs.com/blog/999445/202011/999445-20201106190430283-1506782693.png) ![](https://img2020.cnblogs.com/blog/999445/202011/999445-20201106190436586-439371853.png) ## CSS 佈局框架的特點 CSS 佈局主要有四種,上古時期用的是 table,這個就不說了,我們只討論新世紀常用的 Float、Flex、Grid。這三種佈局方式就是遞進的關係,逐步加強了 CSS 佈局的便利性。CSS 佈局的最佳實踐當屬 Bootstrap,其中 Float 和 Flex 佈局方案都已經被 Bootstrap 實現,唯獨 Grid 方案遲遲不見蹤影。 CSS 佈局框架的關鍵在於如何設計柵格,我們先看看在 Bootstrap 中是怎麼進行佈局的。 ```html .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-1 .col-md-8 .col-md-4 .col-md-4 .col-md-4 .col-md-4 .col-md-6 .col-md-6 ``` 用過 Bootstrap 的人對以上結構一定不陌生。在 Bootstrap v4 中,由於 Flex 佈局功能的增強,`row` 也可以搭配 `utility` 使用。 ```html One of three columns One of three columns One of three columns One of three columns One of three columns One of three columns One of three columns One of three columns One of three columns ``` `row` 和 `col` 的組合幾乎已經成為柵格佈局的共識和標準。接下來我們就用這種設計方式手撕一個 Grid 柵格看看效果。 ## 手撕 CSS 佈局柵格 其實手撕一個 CSS 佈局柵格並不難,關鍵是要熟悉前處理器的迴圈功能。下面我們分別用 Float、Flex 及 Grid 實現一個簡化版的柵格佈局並對比一下它們之間的差異。 ### Float Float 是過去實現流體佈局的唯一方式,難點在於處理父元素的塌陷,這算是一個老生常談的問題了,本文不再贅述。以下是一個簡易版的 Float 柵格:

See the Pen float-columns by Zongbin (@nzbin) on CodePen.

這種柵格簡單實用,堪稱經典。但是 Float 佈局的侷限性很大,如果柵格的高度不相同(比如將第一個柵格的高度加高),佈局就會出現錯位。 ### Flex Flex 的誕生幾乎解決了 Float 柵格的所有痛點,比如上面提到的錯位問題。以下是一個簡易版的 Flex 柵格:

See the Pen flex-columns by Zongbin (@nzbin) on CodePen.

其實在一維佈局中,Flex 已經足夠好用,至少在流體佈局中沒發現特別需要改進的地方,所以我們是否還有必要引入二維佈局方案? ### Grid **重點來了!重點來了!重點來了!** Grid 是比 Flex 更高階的佈局技術,所以單純替換 Flex 實現一套柵格佈局系統完全沒有問題。以下是一個極其簡易的 Grid 柵格,幾乎和 Flex 柵格的效果沒有區別。

See the Pen grid-columns by Zongbin (@nzbin) on CodePen.

Grid 除了能實現 Flex 的佈局之外,還可以在縱向空間對每一行進行調整(比如設定 `grid-template-rows: 1fr 2fr`)。另外,Grid 設定其它列數的柵格也比較容易,比如設定 10 列柵格,只需要設定 `grid-template-columns: repeat(10, 1fr)` 即可;如果是 Flex,則需要重新計算柵格的寬度。 上面示例中展示的 CSS Grid 的功能只是冰山一角。作為一個二維佈局技術,它的屬性寫法非常繁雜,比如另外一個強大的功能 `grid-template-areas` [MDN Demos](https://developer.mozilla.org/zh-CN/docs/Web/CSS/grid-template-areas)。這種屬性定義方式很難使用類名的疊加組合實現對應的功能。 如果只是簡單地將 Flex 柵格替換成 Grid 柵格,我個人感覺意義不大,一個基於 CSS Grid 全新的柵格系統應該儘可能的發揮它所有的優勢。這或許就是 CSS Grid 柵格系統遲遲沒有出現的原因吧。我不知道文章寫到這裡是否清楚的表達了我的觀點,或者說能否解答大家對於開篇問題的疑惑。接下來再看看 `flex-layout` 中的 Grid。 ## Flex-Layout 中的 Grid 因為 `flex-layout` 是基於指令的實現,所以不像類名疊加的方式那樣有很大的侷限性,幾乎可以發揮 CSS Grid 的全部優勢。以下就是 `grid-template-areas` 的定義方法。 ```html Header Sidebar Sidebar 2 Content
More content than we had before so this column is now quite tall. Footer ``` `flex-layout` 無論是設計思路還是實現方式都讓我頂禮膜拜,它與傳統的 Bootstrap 形式的柵格有著本質區別。本文的重點不是介紹 `flex-layout`,如果大家感興趣,還是看官網介紹吧 [Flex-Layout](https://github.com/angular/flex-layout)。 ## 總結 醞釀了兩個月的文章,感覺還是沒有把自己的觀點表達清楚。回到問題本身,【為什麼沒有基於 Grid 佈局的純 CSS 前端框架呢】,個人覺得最主要的還是傳統寫法無法發揮 CSS Grid 的全部優勢,至少用以往的類疊加方式是無法做到的。CSS Grid 屬性的特殊性也決定了不可能也不應該只是單純的疊加組合類