# [CSS] Grid
###### tags: `前端筆記` `style`
1. 外層容器畫線,裡面的子元素畫格子(依照格子佔位)
2. Grid 編排的角度 => 一開始就全部排好,像畫圖填格子一樣
3. Flex 編排的角度 => 由上到下一層一層排好
## 下在外層容器的屬性
- grid-template-columns
- grid-template-rows
- grid-template-areas
### grid-template-columns
- 決定橫向有 n 格
- 決定 寬度
### grid-template-rows
- 決定直向有 m 格
- 決定 高度
### gap
- `grid-row-gap` 及 `grid-column-gap` 的縮寫
#### 外層畫一個 4 X 3 的容器
- 外層容器是畫線。
`grid-template-columns: 1fr 1fr 1fr 1fr;` 一排(橫向)有 4 個格子,每個格子都拿到 1 份外層容器平分後的寬度
- `grid-template-columns: 1fr 1fr 1fr 1fr;` = `grid-template-columns: repeat(4, 1fr);` 會重複寫的可以用 repeat(要重複的次數, 要重複的東西)
`grid-template-rows: repeat(3, 1fr)` 一列(直向)有 3 個格子,每個格子都拿到 1 份外層容器平分後的高度
- 同理,`grid-template-rows: repeat(3, 1fr)` = `grid-template-rows: 1fr 1fr 1fr`
```htmlembedded=
<body>
<div class="wrapper1">
<!-- 畫一個 4 X 3 的格子 -->
</div>
</body>
```
```css=
.wrapper1 {
display: grid;
height: 300px;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: repeat(3, 1fr);
}
```

#### 幫每一格加上間距(gap)
`gap: <grid-row-gap> <grid-column-gap>`
```css=
.wrapper1 {
display: grid;
height: 300px;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: repeat(3, 1fr);
gap: 10px 15px;
}
```

- 每個格子橫向會有 15 px 的間距
- 同理,直向就是 10
## 下在子元素本身的屬性
- grid-column
- grid-row
- grid-area
### grid-column
- `grid-column: <start-line> / <end-line>;`
- 決定子元素橫向佔多少線
- 總線數為外層 grid-template-columns 創造出的 n 個格子 + 1
### grid-row
- `grid-row: <start-line> / <end-line>;`
- 決定子元素直向佔多少線
- 總線數為外層 grid-template-rows 創造出的 m 個格子 + 1
#### 記得子元素 grid-column 及 gird-row 是數線的
```css=
.wrapper1 {
display: grid;
height: 300px;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: repeat(3, 1fr);
gap: 10px 15px; /*<grid-row-gap> <grid-column-gap>*/
.header {
grid-column: 1 / -1;
/* 第 1 條到 - 1 條線 = 第 1 條到最後 1 條線*/
background-color: green;
}
.side-bar {
grid-column: 1 / 2;
background-color: yellow;
}
.content {
grid-column: 2 / -1;
background-color: blue;
}
footer {
grid-column: 1 / -1;
background-color: pink;
}
}
```

## Learn CSS Grid in 20 Minutes 影片範例
### 1. grid-auto-columns / rows
- 為格子的基準寬度 / 高度
- 如果橫向 / 直向的格子數不夠, auto 就會變成沒被設定之格子的寬度 / 高度,如果其他格子使用比例分的大小的,要先扣掉基準才會分比例
- [範例](https://codepen.io/lun0223/pen/vYZqgKe)
- [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0600-0700)
### 2. minmax(最小範圍, 最大範圍)
Q: 如果高度設定固定值,但內文太多造成實際需要的高度會 > 設定值,看起來會怎麼樣呢?
A: 如果是用 `grid-auto-rows` 就會炸出來,因為 `grid-auto-rows` 的基準很強大。這時就要用 `minmax(x, autp)` 讓高度最小為 x ,如果內容超過 x ,就隨著內容長大。

- [範例](https://codepen.io/lun0223/pen/zYzVZXL)
- [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0710-0750)
### 3. 為每個格子命名排版 `grid-template-areas` + `grid-area`
直接在外層元素使用這個屬性(`grid-template-areas`),依名字排版,內層元素(`grid-area: 名字`)在個別命名。
- [範例](https://codepen.io/lun0223/pen/BaZgRQW)
- [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0850-1030)
### 也可以用數線或者數格子(span)
> 一開始在排版的時候就要先安排大區塊,思考整體的安排。
這裡先插入一個小觀念,Grid 大致分兩個區塊:explicit(明確的)& implicit(不明確的)。下列的文章有詳細介紹 XDD。
https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/
#### explicit(明確的)& implicit(不明確的)
##### 1. explicit(明確的)
有明確設定出來的區域(也就是設定中的格式),吃得到外層設定的 `grid-template-columns` & `grid-template-rows` 的比例。
##### 2.implicit(不明確的)
明確區域之外的就是屬於 implicit(不明確的)的區域。此區域吃不到外層設定的排版。
>為什麼會有這個呢?因為子元素的排列超過外層容器規定的線啦。

*因為外層設定垂直向 `grid-template-rows: 150px 200px;` 只有兩格,但是排版的關係 Side-bar 1 跟 Side-bar 2 把垂直的格數佔掉了。所以讓多出來的區域高(height)失靈,但橫向沒超過,所以還是會維持寬(width)。*
#### 不想數線嗎?那就用 `span` 數格子吧!
算格子真的比較簡單...
`gird-column / row: default span 1` 預設都會佔一格。
`span` 就是「算格子」,而 `grid-column / row` 是算「線」。
- [範例](https://codepen.io/lun0223/pen/abwgVrw)
### Grid 的排序與各種對齊方式
#### 該怎麼對齊?
有兩種屬性決定對齊的方式:
##### 1. `justify-items`
`justify-items: start | end | center | stretch (default)` 決定子元素在水平軸上的對齊(橫向)。
##### 2. `align-items`
`Align-items: start | end | center | stretch (default)` 決定子元素在交叉軸上的對齊(直向)。
>道理和 flex-box 差不多,但是不像 flex-box 主線軸的方向(flex-direction)會影響兩個屬性對齊的方向。
#### 如果想要對齊單個子元素呢?
##### 1. `justify-self`
##### 2. `align-self`
範例可以看 [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/#top-of-site)。
#### RWD 組合技
```htmlembedded=
<div class="contaier">
<div class="grid-item grid-item-1">grid-item-1</div>
<div class="grid-item grid-item-2">grid-item-2</div>
<div class="grid-item grid-item-3">grid-item-3</div>
<div class="grid-item grid-item-4">grid-item-4</div>
<div class="footer">Footer</div>
</div>
```
```scss=
body {
background-color: rgba(0, 0, 0, 0.2);
}
.contaier {
border: 1px solid white;
width: 200px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
> * {
border: 1px solid white;
}
.grid-item-1 {
background-color: #ffba08;
}
.grid-item-2 {
background-color: #e85d04;
}
.grid-item-3 {
background-color: #d00000;
}
.grid-item-4 {
background-color: #8ecae6;
}
.footer {
background-color: #a68a64;
}
}
```
##### `grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));`
- repeat(auto-fit, minmax(100px, 1fr))
盡可能的製造出橫向格,每格最小為 100px,超過 100px 每格最多拿到一份平分後的空間。
###### 誰決定有幾個格子?
- 該容器擁有幾個子元素影響有幾個格子
- (min)假設容器的空間是 600px,有六個子元素,那麼每個元素就會分到 100px 的空間。
- (max)假設容器的空間是 600px,但這次只有兩個子元素,那麼每個元素就會分到 300px 的空間。
###### 那麼為什麼可以做 RWD?
只要容器縮小到沒辦法滿足最小的需求 minmax(最小, 最大),那麼就會縮排,讓子元素滿足最大的需求(也就是佔 1fr)。
- [範例](https://codepen.io/lun0223/pen/qBjzVGV)
- https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/
- [Grid 切不同大小的格子 + RWD 設置](https://codepen.io/lun0223/pen/abLbbVJ?editors=1100)
## 之後 Grid 可以看這系列文章重新整理
https://ithelp.ithome.com.tw/users/20001433/ironman/3944
## Grid 容器範例
### 1. 外容器切分兩個項目,單個項目又成為 Grid 容器


### 2. 公司專案:外層容器使用 `grid-template-areas` 定義區塊位置,內層項目使用 `grid-area` 命名位置

簡略版本的 HTML 結構:
```htmlembedded
<!-- 若使用 grid-template-areas 用定義的方式區分區塊,那麼 HTML 的順序沒差,也可以 .content, .menu, .header,但是為了讓結構維持可讀性,還是建議按照順序定義結構 -->
<div class="layout">
<div class="header"></div>
<div class="menu"></div>
<div class="content"></div>
</div>
```
```css
/* 外層容器 */
/* 容器定義項目為 2 x 2 */
.layout {
display: grid;
/* 定義橫向 */
grid-template-columns: min-content auto;
/* 定義直向 */
grid-template-rows: 52px 1fr;
/* 定義區塊位子 */
/* menu 的區塊會佔兩個直向的區塊 */
grid-template-areas:
"menu header"
"menu content";
}
.header {
grid-area: header;
}
.menu {
grid-area: menu;
}
.content {
grid-area: content;
}
```
## 參考資料
1. [CSS Flex & Grid 排版詳解(下):Oh My Grid!](https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/) -> RWD 組合技
2. [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM)
3. [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/#top-of-site) -> 可以看裡面屬性的範例
4. https://grid.malven.co/ -> 屬性範例
5. [CSS Grid 网格布局教程](https://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html)
6. [Less Absolute Positioning With Modern CSS => 其他用 `display: grid` 取代 `position: absolute` 的奇淫技巧](https://ishadeed.com/article/less-absolute-positioning-modern-css/?fbclid=IwAR0Z2NOOvroCvfxEui9RN2eOEAgsGtzxyfEKsVVcyce-gKTUgbPvptpmItQ)
7. [Overlap Elements With CSS Grid Instead Of Position Absolute => masharea 就是用 `display: grid` 讓 UI 能夠重疊](https://pqina.nl/blog/css-grid-position-absolute-alternative/)