## 网格布局详解
设置样式`display:grid`或`display:inline-grid`可以触发网格布局。相对于一维的弹性弹性布局,网格布局提供了更加强大的二维布局能力。
在介绍网格布局的各种能力之前,我们先通过下图明确一下行(`row`),列(`column`),格子区域(`area`)和间隔(`gap`)等概念。
![](https://img.kancloud.cn/ea/c7/eac7ce459f53b60cb190170812cb92ef_520x244.png)
如图,“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`的基准宽度。但是如果剩余可分配空间小于元素本身的宽度的话,元素将会溢出到容器之外,该列元素保持自身的宽度,不会伸缩。
![](https://img.kancloud.cn/a2/5e/a25e3e101885e953db20ca5a9eb6d896_206x84.png)
如图,容器宽度为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`是等价的。
![](https://img.kancloud.cn/29/2e/292e9dd1204544be6d6e8fadb50fd04b_193x84.png)
```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
`的元素在不同宽度下结果如下:
![](https://img.kancloud.cn/c3/de/c3de17d4e428346b1c052bf502345ecf_317x172.png)
### grid-template-rows
该属性定义的各行的高度,与`grid-template-columns`不同的是,该属性不定义行的数量。如果行数超出该属性定义的行数,那么,超出部分按照该行最高元素来定义行高度。
![](https://img.kancloud.cn/c1/c3/c1c3207cfc44dcbf8d3c1bb692e3b054_210x210.png)
```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`使用子元素定义的名称进行布局,布局时可以进行跨行、跨列或者网格区域留空。
该属性的写法为每行用引号(单双均可)引起来,每列之间用空格区分,每行的列数必须一致,跨行则在同一行相邻位置重复使用相应的网格区域名称,跨列则在同一列相邻位置使用相同的网格区域名称,区域留白则使用小圆点(.)代替区域名称。
![](https://img.kancloud.cn/66/83/6683535ef2733bd05604112952bfac0c_519x87.png)
代码如下:
```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'`.
如果,子元素中存在相同名称的网格区域,那么后者将会覆盖前者。
如果,存在留白的网格区域,而存在子元素未声明网格区域名称,那么未声明网格区域名称的元素就将会填充到留白的网格区域。
如果,子元素中存在定义了区域网格名称,但是未引用的话,整个容器形成一种比较诡异的展现形式。
![](https://img.kancloud.cn/80/33/80330319840855734763b7fc8ddb9afc_385x155.png)
```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
- 性能优化
- 常见安全问题
- 进阶
- 工程化
- 前端架构
- 同构
- 高级
- 前端团队管理
- 技术/框架选型
- 持续集成/持续交付
- 经典面试题