## 網格布局詳解
設置樣式`display:grid`或`display:inline-grid`可以觸發網格布局。相對于一維的彈性彈性布局,網格布局提供了更加強大的二維布局能力。
在介紹網格布局的各種能力之前,我們先通過下圖明確一下行(`row`),列(`column`),格子區域(`area`)和間隔(`gap`)等概念。

如圖,“1”,“2”這樣橫向可以占滿整個容器水平方向的稱為一行, “1”,“3”,“5”這樣可以縱向占滿容器垂直方向的稱為一列。“1”,“2”,“3”,“4”,“5”,“5”每個灰色區域稱為一個格子區域,“1”和“2”之間的白色稱為行間隔(`row-gap`), “1”和“3”質檢的白色間隔稱為列間隔(`column-gap`),行間隔和列間隔統稱為間隔。
代碼如下:
```html
<style>
.grid{
display: grid;
width: 500px;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px 10px;
grid-template-areas: 'a b b'
'c . d'
'e f g';
}
.grid>*{
border:1px solid #ccc;
height: 60px;
background: #f8f8f8;
}
</style>
<div class='grid'>
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
<div style="grid-area: d;">4</div>
<div style="grid-area: e;">5</div>
<div style="grid-area: f;">6</div>
</div>
```
### grid-template-columns
該屬性定義了列數以及每列的寬度,這里除了我們常用的單位(如`px`,`%`,`em`等)之外,還可以使用`fr`單位, 也可以使用`auto`(根據所在列最長元素決定該列的寬度)。
類似flex的`flex-grow`, `fr`單位定義的是對剩余空間的分配比例,但是剩余空間分配的計算方法相對簡單,完全按照比例分配,因為該布局方式不存在類似`flex-basis`的基準寬度。但是如果剩余可分配空間小于元素本身的寬度的話,元素將會溢出到容器之外,該列元素保持自身的寬度,不會伸縮。

如圖,容器寬度為200,“1”的寬度時40,兩個間隔分別是10,“2”,“3”剩余可分配空間是200-40-2*10=140, 那么“2”的寬度是140*1/3=46.67, “3”的寬度時140*2/3=93.33.
css代碼如下:
```css
.grid{
display: grid;
width:200px;
grid-gap: 10px;
grid-template-columns: 40px 1fr 2fr;
}
.grid>*{
border:1px solid #ddd;
background: #eee;
height:30px;
}
```
#### repeat(times, width)函數
該函數定義`grid-template-columns`和`grid-template-rows`中定義空間按照指定寬度重復三次,其中times指重復次數,可選值是大于0的數字和`auto-fill`(不指定次數,根據子元素寬度自動排列,超出就換行,此時寬度width不能是fr單位),最小值是1;width需要重復的每列的寬度(或每行的高度),也可以使用fr單位。例如:`grid-template-columns: 40x repeat(2, 1fr)`和`grid-template-columns: 40x 1fr 1fr`是等價的。

```css
.grid{
width:200px;
grid-template-columns: 40px repeat(auto-fill, 60px);
}
```
#### minmax(min, max)函數
該函數定義的是一列的寬度范圍,max小于min時,該值等于min.設置`grid-template-columns: 40px minmax(80px,150px) 1fr
`的元素在不同寬度下結果如下:

### grid-template-rows
該屬性定義的各行的高度,與`grid-template-columns`不同的是,該屬性不定義行的數量。如果行數超出該屬性定義的行數,那么,超出部分按照該行最高元素來定義行高度。

```css
width: 200px;
height: 200px;
grid-gap: 10px;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 30px repeat(2, 1fr);
```
### grid-area 和 grid-template-areas
`grid-area`用于子元素定義子元素的名稱。
`grid-template-areas`使用子元素定義的名稱進行布局,布局時可以進行跨行、跨列或者網格區域留空。
該屬性的寫法為每行用引號(單雙均可)引起來,每列之間用空格區分,每行的列數必須一致,跨行則在同一行相鄰位置重復使用相應的網格區域名稱,跨列則在同一列相鄰位置使用相同的網格區域名稱,區域留白則使用小圓點(.)代替區域名稱。

代碼如下:
```html
<div class='grid' style="grid-template-areas:'a b''c d'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
<div style="grid-area: d;">4</div>
</div>
<div class='grid' style="grid-template-areas:'a a''b c'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
</div>
<div class='grid' style="grid-template-areas:'a b''a c'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
</div>
<div class='grid' style="grid-template-areas:'a .''b c'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
</div>
```
經實驗可知,以下值得設置方式會導致`grid-template-areas`失效:
1. 斜跨列和行,即需要跨行(或跨列)的網格區域未定義在相鄰的行(或列)。例如上圖第一個網格設置成`'a b''c a'`.
2. 存在聲明的區域網格名稱不存在。例如上圖第一個網格設置成`'a b''c e'`.
3. 不是所有行的列數都一致。例如上圖第一個網格設置成`'a b''c'`.
如果,子元素中存在相同名稱的網格區域,那么后者將會覆蓋前者。
如果,存在留白的網格區域,而存在子元素未聲明網格區域名稱,那么未聲明網格區域名稱的元素就將會填充到留白的網格區域。
如果,子元素中存在定義了區域網格名稱,但是未引用的話,整個容器形成一種比較詭異的展現形式。

```html
<div class='grid' style="grid-template-areas:'a b''c d'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
<div style="grid-area: d;">4</div>
<div style="grid-area: d;">5</div>
</div>
<div class='grid' style="grid-template-areas:'a .''b c'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
<div>4</div>
<div>5</div>
</div>
<div class='grid' style="grid-template-areas:'a b''. c'">
<div style="grid-area: a;">1</div>
<div style="grid-area: b;">2</div>
<div style="grid-area: c;">3</div>
<div style="grid-area: d;">4</div>
<div style="grid-area: e;">5</div>
</div>
```
**注意:** 如果在一個元素里同時定義了`grid-template-areas`和`grid-template-columns`且在列數方面有沖突,那么是后定義的覆蓋前面定義的,但是如果`grid-template-columns`用到了`auto-fill`, 那么`grid-template-columns`將會無效。
- 前言
- 基礎
- HTML
- 標簽語義化
- 行標簽和快標簽
- 常用標簽
- 頁面結構
- CSS
- 選擇器
- 盒模型
- 定位
- 單位
- 居中
- 布局
- 擴展:彈性布局詳解
- 擴展:多列布局詳解
- 擴展:網格布局詳解
- 擴展:媒體查詢
- 清除浮動
- 動畫
- 自適應(響應式)
- 兼容性
- 背景
- 文本
- 轉化器
- JavaScript基礎
- 閉包
- 作用域
- 繼承
- 事件
- DOM
- this
- 網絡通信
- ajax
- 跨域
- HTTP狀態碼
- HTTP請求響應頭
- HTTP 2.0
- 請求方法
- Cookie
- 常見框架
- Bootstrap
- jQuery
- Vue
- React
- 性能優化
- 常見安全問題
- 進階
- 工程化
- 前端架構
- 同構
- 高級
- 前端團隊管理
- 技術/框架選型
- 持續集成/持續交付
- 經典面試題