Well in Time
與 CSS Grid 的第一次接觸
02-03-20179 Min Read

好歌分享:Ruby duby feat.Ruby

前言

建構網頁佈局是製作網站的基本動作之一,隨著設計多樣性與功能複雜度的提升,開發者必須利用 table, inline, float, clear, 或是 positioning 等方式來 hack 頁面配置,但不管是哪種方式都各自有其缺乏的功能,也因此催生出許多 CSS Framework 提供的 Grid System 來加速佈局開發。

幾年前出現的 FlexBox 宛如神兵利器,讓我們可以擺脫這些困擾,快速進行排版,而隨著 CSS Grid 規範的出現,我們即將有更好的武器了!

CSS Grid 不是要來取代 Flexbox,他們是相輔相成的角色,flex 可以看作是 one-dimensional layout solutionCSS Grid 則是 two-dimentional layout solution,用來解決我們所有先前需要各種 hack 才能完成的頁面佈局。

不過可惜的是,CSS Grid 還在 W3C working draft 中,並且直到 2017 的今天,還是有些人使用不支援 flex 的舊瀏覽器...

Can I use Css grid

上圖可以得知,Chrome 跟 Firefox 的下一個版本都會預設支援 CSS Grid,而 IE/Edge 目前則是支援舊版本的規格實作的。如果想要先嚐鮮,可以直接下載 Chrome Canary, Firefox Nightly 來使用,或是開啟目前版本的實驗功能:

  • Chrome: chrome://flags -> 啟用 experimental Web Platform features
  • Firefox: about:config -> 啟用 layout.css.grid.enabled

當然也有 Polyfill 可以使用。

雖然生不逢時,但這一切都是過程,活著不難,最難的是做人...啊啊蛋堡的歌真好聽

這篇文章主要是介紹 CSS Grid 的用法,並為我自己做個學習紀錄,畢竟網路上已經有許多關於 CSS Grid 的資源,我也條列了一些在文章最下方,懶得看我廢言的讀者可以自行參考!

CSS Grid Layout

以往我們在進行頁面切版佈局的時候,即便是使用 flexbox,由於他是 one-dimensional layout,我們排版的方式無非就是從上往下排,或是由左到右等方向性來把各種 one-dimensional layout 組合成我們要的 two-dimensional layout

CSS Grid 不同的地方就在於,他讓我們先定義好一個 container 就夠了,一個 container 來設定好所有底下元件可以擺放的位置

什麼是“可以擺放的位置“呢?先跳過實作過程與這些屬性值的意思,以下面這張結果圖來解釋一下,你設定好 CSS Grid 的 container 後,該 container 會長成這副德性:

.container {
  grid-template-columns: 100px 10px 0.3fr 0.7fr;
  grid-template-rows: 25% 100px auto;
}
Grid Container

然後你就只要把 container 內的元素,一一定義好各自的 CSS 屬性,來決定他們要擺在這圖中的哪個空格內即可。 只要兩行 css,一個 div 就排好了,是不是很讓人興奮啊啊啊!

好的,接下來認真說明 CSS Grid 的其他基本用法。

CSS Grid Terminology

再開始嘗試實作之前,我們先來了解並記憶一下相關的術語。

  • Grid Line: 分隔元素的線,可以是垂直與水平,如下圖的紅色線
  • Grid Track: 兩條分隔線中間的區域,簡單想就是 Grid 中的 Columns 或 Rows,如下圖的綠色區塊
  • Grid Cell: Grid 中的基本單位,四條線組成的區域,如下圖的藍色區塊。
  • Grid Area: 由數個 Cell 組成的區域,如下圖的紅色區塊。
  • fr: track-size 的單位,通常用於分配 row 或 column 的非彈性尺寸設定完後之剩餘空間。以下圖的 column為例,意思即:將去掉 100px 與 10px 後的剩餘空間,分配為 30% 與 70%。
Grid Terminology

Simple CSS Grid Example

接著我們把上面的圖片,用 CSS Grid 來 layout 出來。

CSS Grid 的 properties 可以切成兩大塊,一塊是給 Parent 的,也就是 Grid Container,另一塊給 Children,Grid items

詳細的 properties 介紹可以看這篇 Complete Guide Grid ( 強力推薦閱讀,各種圖片文字輔以 css 說明,完全可以直接左轉出去看這篇就好 XD )

要使用 CSS Grid 就必須先定義好 Grid Container:

<div class="grid-container">
  <div class="grid-item item-a">Tack</div>
  <div class="grid-item item-b">Cell</div>
  <div class="grid-item item-c">Area</div>
</div>

在 grid container 底下的 children 是沒有順序差別的,我們都可以透過定義 grid items 的 properties 來設定他的擺放位置。當然,如果你沒有設定的話,就會照順序放置,如果該列放不下就會自動放到下一行。

但基本上不會這麼做,畢竟我們就是想要能好好掌控位置啊!

Grid Container 的 css 可以用下面兩種方式來寫,grid-template-columns 用來定義這個 Grid 有幾個 columns,每個 column 可以有多少寬度;換而言之,grid-template-rows 就是用來定義 row 的屬性。

grid-template-columnsgrid-template-rows 有兩個主要 Values 可以設定:

  • track-size:可以是任何長度(px)、百分比(%)或是先前提到的 fr
  • line-name:組成 column 與 row 的線的名字
.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}

也就是說,你可以用純數字的方式來給予屬性質:

.grid-container {
  height: 100vh;
  display: grid;
  grid-template-columns: 100px 10px 0.3fr 0.7fr;
  grid-template-rows: 25% 100px auto;
}

也可以安插 Grid Line 的名字在屬性值的設定中,這個名字在後續我們要安置 children 時可以用到! [Note] 要注意,因為是定義 的名字,所以最後一個數字的後面也可以定義名字喔!

.grid-container {
  height: 100vh;
  display: grid;
  grid-template-columns: [line1] 100px [line2] 10px [line3] 0.3fr [line4] 0.7fr [end];
  grid-template-rows: [row-1-start] 25% [row-2-start] 100px [row-3-start] auto [row-end];
}

這樣我們就定義好需要的 Grid Container 了。

接著,我們說明一下如何將前面的圖片中的 ** Area ** 這個 Grid Item 放到我們剛剛定義好的 Grid Container 中,因為他的位置比較特殊,在右下角的位置,較好展現 CSS Grid 方便之處。

Grid Item 的屬性基本上就是四個:grid-column-start, grid-column-end, grid-row-startgrid-row-end,你也可以簡化成兩個:grid-columngrid-row

grid-column-start, grid-column-end, grid-row-startgrid-row-end 可以有四種 Values 設定:

  • line: 對照到 Grid Container 中定義的線,可以是數字或名字。
  • span [number]:該 item 會橫跨 [number] 個 tracks。
  • span [name]:該 item 會橫跨到名字是 [name] 的線為止。
  • auto:自動放置,類等於 span 1。
.item-area {
  background-color: #C57474;
  grid-column-start: line2;
  grid-column-end: end;
  grid-row-start: row-3-start;
  grid-row-end: row-end;	
}

若只用兩個屬性,中間以 / 隔開:

.item-area {
  background-color: #C57474;
  grid-column: line2 / end;
  grid-row: row-3-start / row-end;
}

以此類推,完成的範例如下:

See the Pen CSS-Grid-Sample by Arvin (@arvin0731) on CodePen.

Another CSS Grid Example

Container 不只有上面的寫法,還有一個叫做 grid-template-areas 的東西,搭配 Grid-Item 的 grid-area 可以有更簡單的寫法來進行排版。

我們這邊換個例子,以一般網頁較常見的配置來說明:

See the Pen CSS-Grid-Sample-Area by Arvin (@arvin0731) on CodePen.

用了 grid-template-areas 後,在 container 的 css 中,我們可以直接定義每個元素的位置:

.grid-container {
  height: 100vh;
  display: grid;
  grid-template-columns: 0.25fr 0.25fr 0.25fr 0.25fr;
  grid-template-rows: auto;
  grid-template-areas: "header header header header"
                       "main main . sidebar"
                       "footer footer footer footer";
  grid-column-gap: 10px;
  grid-row-gap: 15px;
}

裡面的 header, main, sidebarfooter 就是在 Grid-Item 中我們要指定的名稱:

grid-template-areas 的每一行定義了 Grid-Item 內容:

  • 第一行代表:header 要佔據四行。
  • 第二行代表:main 佔兩行,而 sidebar 佔一行,其中 · 類似 placeholder 的作用。
  • 第三行代表:footer 佔四行。
.header {
  background-color: #8BC574;
  grid-area: header;
}

.main {
  background-color: #748CC5;
  grid-area: main;
}

.sidebar {
  background-color: #C57474;
  grid-area: sidebar;
}

.footer {
  background-color: #FCE052;
  grid-area: footer;
}

此外,grid-column-gapgrid-row-gap 可用來設定行距。

One more thing

除了上述的基本屬性運用外,最前面有說過 CSS Grid 跟 Flex 是相輔相成,而實際上他們可以調配的屬性也有類似的地方。

Grid Container 可以用 justify-itemsalign-items 來控制每個 Grid-item 的 垂直水平 位置。

Grid Item 則是可以用 justify-selfalign-self 來控制自己在網格中的位置。

像這個範例中的 Sidebar

See the Pen CSS-Grid-Sample-align by Arvin (@arvin0731) on CodePen.

歡迎大家參考這幾個個超詳細圖解說明:

Complete guide grid - justify-items Complete guide grid - align-items Complete guide grid - justify-self Complete guide grid - align-self

Conclusion

用幾個簡單的範例來學習並介紹 CSS Grid,但還是希望大家都能直接去 Codepen 上玩玩看 CSS Grid,一定都會被其方便性給驚豔到! 前端發展雖然百家爭鳴,但是很多基本的規範如果能越來越統一越來越強大,開發者就更能省去各種 hacking 的時間,用來創造更多有創意又有美感的作品!

最後再推薦一個網站 Grid by Example,裡面用許多範例來進行教學,頁面也很清楚乾淨。 有任何問題都歡迎大家指教!

資料來源

  1. A Complete Guide to Grid
  2. Chris House Guide to Grid
  3. CSS Grid 介紹
  4. Grid by Example
  5. css-grid-polyfill
© by Arvin Huang. All rights reserved.
theme inspired by @mhadaily
Last build: 05-05-2023