近來因為RWD的興起,flex跟grid的排版方式開始流行了起來。但是大部分的文章都在介紹如何使用,所以想寫一篇文章比較兩者的優勢,以及在什麼情況下用哪一個排版方式比較好。

$cover

前言

注意

本篇適合已了解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

  • 因為最早gapgrid特有的功能,所以不用特別計算寬度,但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

優點

  1. CSS程式碼簡短,預設流向是橫的
  2. 有多個區塊時,可以輕鬆的達到畫面置中的效果
  3. 當前一個區塊是空的時,下一個可以很順利地替補上去

缺點

  1. 要換行需要另外打flex-wrap:wrap比較麻煩,雖然說grid所需的CSS程式碼更多一些就是
  2. 使用flex-direction修改流向成直的,置中的設定會互相調換需要注意一下
  3. 複雜的排版會需要很多層flex去達成,日後維護也會較麻煩

Grid

優點

  1. HTML程式碼簡短,CSS設定較集中,預設流向是直的
  2. 因應不同裝置挪動區塊位置非常簡易
  3. 可以無視資料流向延伸區塊位置

缺點

  1. 學習成本較高、需要打的CSS程式碼較多
  2. 當前一個區塊是空的時,下一個替補的區塊會維持前一個區塊的大小
  3. grid-template有兩個以上的區塊,則無法達到完全置中