# Grid 格線佈局
透過設定欄(column)列(row)來達成像表格那樣的排版。
可分為外層的容器(container)與內層的項目(item),有各自的屬性可設置。
> 如果在一個方向上排列內容項目,應該使用Flexbox 會比Grid更加靈活,且程式碼少易維護;但是,如果要在兩個維度(包括欄和列)中建立整個佈局,則可使用 Grid
## 外容器 Grid container
在父層設置display:grid
```css!
.container {
display: grid;
}
```
---
## 使用 grid-template-columns/rows 設定格線欄/列
利用 <span class='red'>`grid-template-columns`</span> 來設定格線上的 **column**;用 <span class='red'>`grid-template-row`</span> 來設定格線的 **row**,在絕對意義上來說就是 height。
> grid-template-rows 是縱軸,grid-template-columns 則是橫軸

```htmlmixed!
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
</div>
```
```css!
.container {
display: grid;
width: 600px;
height: 400px;
grid-template-columns: 120px 80px auto 1fr 2fr;
grid-template-rows: 100px 1fr 2fr;
gap: 10px;
}
```
<iframe height="410.8642578125" style="width: 100%;" scrolling="no" title="Untitled" src="https://codepen.io/mileyho/embed/QWYBbmz?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/QWYBbmz">
Untitled</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### grid-template
結合 grid-template-column 和 grid-template-row
```css!
.container {
display: grid;
gap: 10px;
grid-template: 120px 80px auto 1fr 2fr / 100px 1fr 2fr;
/* 列(row)每格的寬度 / 欄(column)每格的寬度 */
}
```
---
## 調整容器內欄列大小的單位
grid屬性可用的單位,px、%、em、auto、fr…皆可。
### fr (fractional)
* 只有在 Grid 出現的格線單位,是佔比(幾分之幾)的意思。1fr 是一等分的意思,2fr 就是兩等分,以此類推。
```
grid-template-rows: 2fr 1fr 1fr;
grid-template-columns: 2fr 1fr 1fr;
```
* 也可以和自定義的數值混用,這樣的話就會扣掉固定數值,剩下的寬(高)再平分。
```
grid-template-rows: 30% 100px 1fr 1fr;
grid-template-columns: 200px 1fr 1fr;
```
範例:
當我們把第四個 column 設為 2fr,而前三個設為 1fr 的時候,代表把自由空間各分配 1 份給前三個 column,分配兩份給第四個 column (grid-template-rows: 1fr 1fr 1fr 2fr)
<iframe height="200" style="width: 100%;" scrolling="no" title="Grid-1" src="https://codepen.io/mileyho/embed/xxMJObq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/xxMJObq">
Grid-1</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### auto
* 使用 auto 代表依內容決定寬度,要注意和 fr 是不同的概念。
---
## 利用 repeat() 來簡化欄列的寫法
**repeat(格數, 格寬/高)**
**範例 1:**
```
grid-template-columns: 1fr 1fr 1fr 1fr;
```
使用 repeat() 簡化成
```
grid-template-columns: repeat(4, 1fr);
```
**範例 2:**
```
grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr;
```
使用 repeat() 簡化成
```
grid-template-columns: repeat(4, 1fr 2fr);
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid-1" src="https://codepen.io/mileyho/embed/JjxBBQv?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/JjxBBQv">
Grid-1</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
**問:**
那麼這樣有幾欄呢?
```
grid-template-columns: 200px repeat(4, 1fr 2fr) auto;
```
---
## auto-fill / auto-fit
當我們使用 <span class='red'>`repeat()`</span> 時,可以在第一個參數設定第要重複的次數是 <span class='red'>`auto-fill`</span> 或 <span class='red'>`auto-fit`</span>。
若是不知道數量的情況下,這時就可以使用 <span class='red'>`auto-fit`</span> 或 <span class='red'>`auto-fill`</span> 自動填滿。
* ### auto-fill
會根據 grid 子層寬度自動計算需要填充的數量,若父層寬度大於子層許多的話,就會產生隱藏的欄位
* ### auto-fit
和 auto-fill 類似,視覺上的效果是會將原本欄位內的子層寬度都平均拉長,但實際上還是有新增欄位數,只是被摺疊起來了
<iframe height="360" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/JjxBeJy?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/JjxBeJy">
Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
---
## minmax
**minmax(最小值, 最大值)**
可以利用<span class='red'>`grid-template-columns`</span>搭配<span class='red'>`minmax`</span>做出**RWD**效果。
例如設定成 `minmax(100px,1fr)` ,意思就是最小寬度是 100px,而最大寬度則是自動1等分。
範例:
```
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/MWLBPQR?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/MWLBPQR">
Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
---
## grid-auto-rows / grid-auto-columns
<span class='red'>`grid-auto-rows`</span> 或 <span class='red'>`grid-auto-columns`</span>可以用來簡單設定 rows 或 columns的長度。
### grid-auto-rows
```css!
.container {
display: grid;
width: 50vw;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 100px;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/yLZxwGY?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/yLZxwGY">
Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### grid-auto-columns
```css!
.contaner {
display: grid;
grid-auto-columns: 200px;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-columns" src="https://codepen.io/mileyho/embed/JjxaWJa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/JjxaWJa">
Grid grid-auto-columns</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
或是利用 <span class='red'>`grid-auto-rows`</span>來設定自動產生的 rows 的長度
```css!
.container {
display: grid;
grid-gap: 20px;
grid-template-rows: 50px 200px;
grid-auto-rows: 100px;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-rows 3" src="https://codepen.io/mileyho/embed/LYqJWJa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/LYqJWJa">
Grid grid-auto-rows 3</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
當定義出 columns 的數量時,多出來的子元素會「換行」到下一個 row
```css!
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: 100px 200px;
grid-template-rows: 50px 100px;
grid-auto-rows: 150px;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-columns" src="https://codepen.io/mileyho/embed/XWOPMqq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/XWOPMqq">
Grid grid-auto-columns</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
---
## grid-auto-flow
像 <span class='red'>`flex-direction`</span> 這個屬性,用來控制排序要水平的還是垂直
```
grid-auto-flow: row;
grid-auto-flow: column;
grid-auto-flow: dense;
grid-auto-flow: row dense;
grid-auto-flow: column dense;
```
grid 的預設值是垂直排列 <span class='red'>`row`</span>,當設定的 template 排完後,接著就會往下一列排列,所以如果是水平排列的話(先從上往下排列好後,往旁邊繼續排列)就要改成 <span class='red'>`grid-auto-flow: column;`</span>
### grid-auto-flow: row;
```css!
.container{
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: row;
}
```
使用grid-template屬性指定Grid的欄數為2欄
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/eYxLyoK?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/eYxLyoK">
Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### grid-auto-flow: column;
```css!
.container{
display: grid;
grid-auto-flow: column;
}
```
<iframe height="200" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/BaMOWRN?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/BaMOWRN">
Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
使用grid-template屬性指定Grid的列數為2列
```css!
.container{
display: grid;
grid-template-rows: 1fr 1fr;
grid-auto-flow: column;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow row" src="https://codepen.io/mileyho/embed/gOqdoNr?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/gOqdoNr">
Grid grid-auto-flow row</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### grid-auto-flow: dense;
假如欄寬列高超過 template 的設定,grid 就會自動往下一行,這樣就會產生空白欄位,這邊我們就可以使用 <span class='red'>`dense`</span> ,利用其他合的欄寬補足空白
<iframe height="400" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/MWLBLaP?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/MWLBLaP">
Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
<iframe height="300" style="width: 100%;" scrolling="no" title="CSS Grid Responsive Image Gallery" src="https://codepen.io/ramenhog/embed/MpORPa?default-tab=result&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/ramenhog/pen/MpORPa">
CSS Grid Responsive Image Gallery</a> by Stephanie (<a href="https://codepen.io/ramenhog">@ramenhog</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
<iframe height="300" style="width: 100%;" scrolling="no" title="Guided" src="https://codepen.io/ycw/embed/LgJEor?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/ycw/pen/LgJEor">
Guided</a> by ycw (<a href="https://codepen.io/ycw">@ycw</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
---
## 項目 grid Item
### grid-[row/column]-start / grid-[row/column]-end
物件所佔的空間位置,column 及 row 所到的起始點及終點
```
.item {
grid-column-start: <number> | <name> | span <number> | span <name> | auto
grid-column-end: <number> | <name> | span <number> | span <name> | auto
grid-row-start: <number> | <name> | span <number> | span <name> | auto
grid-row-end: <number> | <name> | span <number> | span <name> | auto
}
```
* `<line>` - 用數字表示 物件 所在的線
* `span <number>` - 物件所佔用的欄位數
* `span <name>` - 物件所在的 grid 名稱
* `auto` - 自動,設定 auto 通常為 start 值 +1

```css!
.itemA{
grid-row-start: span 2;
/* 起始為跨兩格*/
grid-row-end: -1;
/* 終點為倒數第一條線 */
/* 負值為倒數數過來 */
grid-column-start: 2;
/* 起始欄位第2條線 */
grid-column-end: span 2;
/* 結束欄位線,從第二條線跨兩格 */
}
```
> **span**:跨越幾個區塊
>
### 合併: grid-[row/column]: start / end
```css!
.itemA{
grid-row: span 3 / -1 ;
/* startline / endline */
grid-column: 2 / span 2 ;
/* startline / endline */
}
```
如果只寫2,代表2-3的單位
```css!
.itemA{
grid-row: 2;
/* == grid-row: 2 / 3; */
}
```
### 大合併: grid-area
```css!
.itemA{
grid-area: span 3 / 2 / -1 / span 2 ;
/* row-start / column-start / row-end / column-end */
}
```
<iframe height="500" style="width: 100%;" scrolling="no" title="Grid grid-auto-rows 2" src="https://codepen.io/mileyho/embed/LYqJyPw?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/LYqJyPw">
Grid grid-auto-rows 2</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
---
## 自訂格子和線的名字
使用 <span class='red'>`grid-template-columns` </span>和<span class='red'> `grid-template-rows`</span>畫好格子之後,也可以使用 <span class='red'>`grid-template-area`</span> 為特定的格子命名,並指定要將什麼元素放在此格子裡。
### grid-template-areas
* 區塊如果要合併,必須要連續,像ㄇ形或L型是不行的
* 定義完後,子元素必須加入 `grid-area` 指定區塊
* 使用<span class='red'>` . `</span>可以留空區塊
```css!
.container {
display: grid;
grid-template-rows: 60px 300px 300px;
grid-template-columns: 200px 1fr 1fr;
grid-template-areas:
"nav nav nav"
"sidebar content-01 content-02"
"sidebar content-03 content-04";
/* (x) 倒L型 nav
* grid-template-areas:
* "nav nav nav"
* "nav content-01 content-02"
* "nav content-03 content-04";
*/
}
.nav {
grid-area: nav;
}
.sidebar {
grid-area: sidebar;
}
.content-01 {
grid-area: content-01;
}
.content-02 {
grid-area: content-02;
}
.content-03 {
grid-area: content-03;
}
.content-04 {
grid-area: content-04;
}
```
<iframe height="500" style="width: 100%;" scrolling="no" title="grid-template-areas" src="https://codepen.io/mileyho/embed/eYxLVaq?default-tab=result&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/eYxLVaq">
grid-template-areas</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
```css!
.container{
display: grid;
grid-template-rows: 1fr 2fr 2fr;
grid-template-columns: 2fr 1fr 1fr;
grid-template-areas:
"a a ."
"a a ."
". b c";
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="grid-template-areas" src="https://codepen.io/mileyho/embed/BaMOEQB?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/BaMOEQB">
grid-template-areas</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
命名之後的區域,也可以搭配 <span class='red'>`grid-row`</span> 和 <span class='red'>`grid-column`</span>,直接定義要從哪個命名區塊開始或結束
### 為格線命名
可以使用 <span class='red'>`[]`</span> 為格線命名,以便之後指定元素在格線上的位置時使用,一條格線可以不只一個命名,有點類似 CSS 的 class,可以有多重命名。
```css!
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: [sidebar-start site-left] 1fr [sidebar-end content-start] 500px [content-end] 1fr [site-right];
grid-template-rows: [content-top] repeat(10, auto) [content-bottom];
}
.item3 {
background: slateblue;
grid-column: content-start;
grid-row: content-top / content-bottom;
/* grid-row: 1 / span 10; */
}
```
---
## gap
各區塊之間的間距,可以一起設定,也可以用 `row-gap` 和 `column-gap` 分開設定。
---
## 對齊方式
### justify-content
* 作用範圍: Grid容器。
* 作用對象: 用於設定Grid容器內所有子項目在主軸上的對齊方式。
```
justify-content: start | end | center | stretch | space-between | space-around | space-evenly
```
<iframe height="300" style="width: 100%;" scrolling="no" title="grid-auto-flow span" src="https://codepen.io/mileyho/embed/ExrBZLw?default-tab=css%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/ExrBZLw">
grid-auto-flow span</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### justify-items
* 作用範圍: Grid容器。
* 作用對象: 於設定Grid容器內所有子項目的默認對齊方式,可以被單個網格項目的justify-self屬性覆蓋。。
```
justify-items: start | end | center | stretch |
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid justify-content" src="https://codepen.io/mileyho/embed/JjxQJwv?default-tab=css%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/JjxQJwv">
Grid justify-content</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### justify-self
### align-items
```
align-items: start | end | center | stretch
```
### align-self
* 在 grid 容器上設定 <span class='red'>`justify-items`</span> 可以決定所有的 grid 子元素在水平線(主軸)上怎麼對齊,設定 <span class='red'>`align-items`</span> 可以設定所有的 grid 子元素在垂直線(交叉軸)上要怎麼對齊。
* 若只想要改變某個 grid 元素的對齊方式,可在子元素上設定 <span class='red'>`justify-self`</span> 即 <span class='red'>`align-self`</span>。
* 大致用法都和 flex 排版的原理相通。
---
## 排序:order
利用order來改變排列順序,所有子元素的預設 order 是 0,但是順序可以被任意設置為正數或者負數。
```css!
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(10, 1fr);
}
.logo {
grid-column: span 2;
order: 2;
}
.nav {
grid-column: span 8;
order: 1;
}
.content {
grid-column: 1 / -1;
order: 3;
}
```
<iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-area" src="https://codepen.io/mileyho/embed/LYqJyJN?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/mileyho/pen/LYqJyJN">
Grid grid-area</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
## justify-self, align-self
---
[**Grid by Example 🌐**](https://gridbyexample.com/) --提供大量關於 CSS Grid 的範例和資源,從基礎到進階的都有
[**Grid 小遊戲 🌐**](https://cssgridgarden.com/#zh-tw)
[**Amos 影片教學 🌐**](https://www.youtube.com/watch?v=fYcz3FUqv7M)
<style>
.red{
color: crimson;
}
</style>