近來因為RWD的興起,flex跟grid的排版方式開始流行了起來。但是大部分的文章都在介紹如何使用,所以想寫一篇文章比較兩者的優勢,以及在什麼情況下用哪一個排版方式比較好。
前言
注意
本篇適合已了解flex及grid用法的人閱讀,因為本篇不會介紹如何使用它們。
如果要用一句話來描述兩者的差異,那就是Flex
是擅長一維的排版,Grid
擅長二維的排版。
就像數學的座標軸一樣:
- 如果資料的流向是只有x或只有y,那麼用flex會比較適合。
- 如果流向是在x、y之間格狀的區塊,那麼用grid會比較適合。
雖然是這麼說,但隨著CSS跟瀏覽器的進步,其實兩者之間的差異性也越來越小了。
實戰
範例一:列表(資料單向排列,資料本身沒有固定長度,且會換行)
Flex
- 列表雖然大部分都用
li
去做,但是flex
也是可以很輕鬆做到的
Grid
- 如果沒有指定寬度,
grid
會自動平均分配空白的空間至滿版,且無法斷行。如果指定寬度,就有可能造成文字斷行不美觀的問題
範例二:卡片列表(資料單向排列,資料有固定長度,且會換行。資料不達一行時則置中)
Flex
- 相較於範例一,
flex
只需要在子層加上flex
的比例即可,因為我有加gap
所以在寬度上計算上會稍微複雜一些(基本的寬度為100% / 3
、gap的寬度為2rem / 3
)。- 不滿一行置中的設定也是相當容易,用程式判斷並添加
justfy-content:center
即可。
Grid
- 因為最早
gap
是grid
特有的功能,所以不用特別計算寬度,但grid在沒有資料的情況下仍然會佔據空間導致無法達到水平置中的效果。
範例三:不規則區塊(A為sidebar,B、C、D為資料區塊。當C沒有資料時,D可以選擇在原位置還是替補C的位置)
Flex
- 如果要切出A、B、C、D四個區塊,對
flex
稍微麻煩,需要橫向一層再包縱向一層。- D替補C區塊的時候,仍然保持D區塊的高度
- D佔據C區塊的時候,
flex-grow
調高到1即可
Grid
- 如果要切出A、B、C、D四個區塊,對
grid
來說輕而易舉,只需要一層就可以切出來。(grid-template
裡輸入的1fr
代表佔據比例跟flex-grow
一樣,而auto就是遵循子層的高度)- 執得一提的是,D替補C區塊的時候,仍然是延續C區塊的高度,不會維持原本的高度。(這邊不討論用JS修改
grid-template-columns
的高度)- 如果要佔據C區塊則使用
grid-row: span 2;
即可
總結
其實在寫這篇文章之前我是比較常用grid框架的,因為我不喜歡太多層讓架構變很複雜,但是在完成三個例子後我發現,其實很多不太複雜的架構,用flex做會比grid彈性來得大(畢竟他的中文翻譯也叫彈性盒子)。
下面是我私心覺得的優缺點:
Flex
優點
- CSS程式碼簡短,預設流向是橫的
- 有多個區塊時,可以輕鬆的達到畫面置中的效果
- 當前一個區塊是空的時,下一個可以很順利地替補上去
缺點
- 要換行需要另外打
flex-wrap:wrap
比較麻煩,雖然說grid所需的CSS程式碼更多一些就是 - 使用flex-direction修改流向成直的,置中的設定會互相調換需要注意一下
- 複雜的排版會需要很多層flex去達成,日後維護也會較麻煩
Grid
優點
- HTML程式碼簡短,CSS設定較集中,預設流向是直的
- 因應不同裝置挪動區塊位置非常簡易
- 可以無視資料流向延伸區塊位置
缺點
- 學習成本較高、需要打的CSS程式碼較多
- 當前一個區塊是空的時,下一個替補的區塊會維持前一個區塊的大小
- 在
grid-template
有兩個以上的區塊,則無法達到完全置中