前面我们讲到了一种非常方便的布局方式flex,也提到了他是一种非常方便的一维布局解决方案,那么二维呢?我们有Grid。
作为一个二维布局,它远比flex来的强大。
什么是Grid
Grid布局,也就是我们所谓的网格布局,它可以轻松实现容器内子元素的任意位置布局(将我们的外部容器分为一个个的网格,然后在任意一个网格内放入我们想要放入的子元素),他比flex强大很多,但可惜的是,他在部分浏览器中的支持并没有flex那么普及,所以在考虑到兼容性的情况下,我们可能很少会去采用这一种布局的方式,但是这并不影响我们学习他。(对于某些项目来说,可能只需要支持某一个特定的浏览器,这个时候,Grid布局就会有很大的用武之地)和flex一样,想要把一个容器设置为grid容器也非常的简单,只需要讲他的display属性设置为grid。
.box{
display: grid | inline-grid;
}
容器的属性

在了解容器的属性之前,我们首先需要了解以下在网格布局中非常重要的两个概念,行(row)和列(column)。在上面这幅图中,有横竖总共8条表格线,将一个容器分为了3行和3列,在我们的网格布局中,属性往往是两两出现,分别对应行和列,因此我们可以根据作用是否相同将他们进行一个分组。
- grid-template-columns和grid-template-rows
- grid-row-gap、grid-column-gap和grid-gap
- grid-template-areas
- grid-auto-flow
- justify-items、align-items和place-items
- justify-content、align-content和place-content
- grid-auto-columns和grid-auto-rows
- grid-template和grid
1.grid-template-columns和grid-template-rows
grid-template-columns:用于定义每一列的列宽
grid-template-rows:用于定义每一行的行高
对于这两个属性我们可以有很多种方式的值。
(1)直接使用px值
比如我们要实现一个上面这幅图所展示的表格我们可以这样来写(假设每一个单元格的宽高都是100px):
.box{
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
(2)使用百分比
如果box的宽高已经固定为300px,我们还可以使用百分比来实现上面的内容
.box{
display: grid;
grid-template-columns: 33.3% 33.3% 33.3%;
grid-template-rows: 33.3% 33.3% 33.3%;
}
(3)fr关键字
grid提供了一个关键字fr(片段,fraction的缩写),他代表一个比例关系,所以上面这段代码我们又可以改成这样:
.box{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
这代表了1:1:1的关系。如果1fr 2fr 3fr,则代表了1:2:3的关系。还有一点值得注意的是,fr还可以和px值配合使用,比如grid-template-columns: 100px 1fr 1fr,代表第一列为100px,剩下两列为1:1的关系。
(4)repeat函数
我们还可以用repeat函数来写上面这个方法,他支持两个参数,第一个参数是重复的次数,第二个参数是需要重复的值。
.box{
display:grid;
grid-template-columns: repeat(3, 1fr); /* 这里的1fr当然也可以是100px或者33.3% */
grid-template-rows: repeat(3, 1fr);
}
第二个参数还可以传递某种组合,比如这样grid-template-columns: repeat(2,100px 200px),这样就会生成一共四列,其中第一第三列为100px,第二第四列为200px。
(5)auto-fill关键字
这是配合repeat函数使用的一个关键字,可以在父元素宽高不固定的时候使用。grid-template-columns: repeat(auto-fill, 100px),这段代码表示用宽度100px的列来填充容器,知道填充不下为止。
(6)auto关键字
自适应,grid-template-columns: 100px auto,比如这一段代码,代表了第一列的宽度为100px,第二列宽度自适应,会自动填充满容器的宽度。(当然也会有特殊情况比如单元格有min-width)
(7)minmax函数
产生一个长度范围,接受两个参数,分别为最小值和最大值,比如这样一段代码:grid-template-columns: 1fr minmax(100px, 1fr),代表第二列的宽度大于100px,且小于1fr。
(8)网格线的名称
我们可以给网格线来设置名称,比如这样:grid-template-columns: [c1] 100px [c2] auto [c3 end-line],我们可以看到同一根先还可以有不同的名字。
2.grid-row-gap、grid-column-gap和grid-gap
grid-row-gap:用于设置行与行之间的间距(行间距)
grid-column-gap:用于设置列与列之间的间距(列间距)
grid-gap:上面两个值的合并写法,语法grid-gap: <grid-row-gap> <grid-column-gap>,当然他也可以值传递一个参数,代表第二个值和第一个值相等。
按照最新的标准这三个属性的grid前缀可以省略,分别写成row-gap,column-gap和gap。
3.grid-template-areas
用于给单元格进行命名,可以是一个单元格代表一个区域,也可以是多个单元格代表一个区域:
.box{
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas:'a b c'
'd e f'
'g g g';
}
区域命名还会直接影响到网格线的名称区域名-start,区域名-end
4.grid-auto-flow
可以是row、column、row dense和column dense四个值中的其中一个,表示子元素的排列规则,其中row表示先行后列,column表示先列后行。而dense表示尽可能填满,不出现空格,假设我们有a,b,c三个元素,宽度都为50%,然后我们将a,b元素上下排列,然后如果使用row排序,c元素灰出现在b元素的后面,但是如果我们使用row dense排序,c的位置就来到了a的后面,如下例:
<style>
.box{
display: grid;
grid-template-columns: 100px 100px;
grid-template-rows: 100px 100px;
}
.item {
font-size: 4em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: red;
grid-column-start: 1;
grid-column-end: 2;
}
.item-2 {
background-color: green;
grid-column-start: 1;
grid-column-end: 2;
}
.item-3 {
background-color: yellow;
}
</style>
<div class="box">
<div class="item item-1">a</div>
<div class="item item-2">b</div>
<div class="item item-3">c</div>
</div>
效果如下图:

现在我们给box中加上
grid-auto-flow: row dense;效果变成了这样。
5. justify-items、align-items和place-items
justify-items:设置单元格内容的水平位置(左中右)
align-items:设置单元格内容的垂直位置(上中下)
他们都可以有以下四个值:
- stretch:拉伸,占满单元格的整个宽度(默认值)
- start:对齐单元格的起始边缘
- end:对齐单元格的结束边缘
- center:单元格内部居中
.box{
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}
place-items是以上两个值的合并简写:
place-items: <align-items> <justify-items> /* 如果两个值相等则可以省略第二个值。*/
6.justify-content、align-content和place-content
主要作用于网格的内容区域没有完全填满容器的情况下。
justify-content:整个内容区域在容器里面的水平位置(左中右),
align-content:整个内容区域的垂直位置(上中下)。
.box{
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
- start:对齐容器的起始边框
- end:对齐容器的结束边框
- center:容器内部居中
- stretch:项目大小没有指定时,拉伸占据整个网格容器
- space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍
- space-between:项目与项目的间隔相等,项目与容器边框之间没有间隔
- space-evenly:项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔
place-content是align-content和justify-content的合并简写形式。
place-content: <align-content> <justify-content> /* 如果两个值相等则可以省略第二个值。*/
7.grid-auto-columns和grid-auto-rows
当一些项目所在的位置超出我们现有网格的时候,可以用这两个属性来规定自动生成的网格的宽高。
8.grid-template和grid
grid-template是grid-template-columns、grid-template-rows和grid-template-areas的合并简写形式。
grid是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow的合并简写形式。
项目的属性
接下来我们来看项目上可以使用哪些属性,我们依旧是分组来看:
- grid-column-start、grid-column-end、grid-row-start和grid-row-end
- grid-column和grid-row
- grid-area
- z-index
- justify-self、align-self和place-self
1.grid-column-start、grid-column-end、grid-row-start和grid-row-end
这四个属性用于指定项目的具体位置:
grid-column-start属性:左边框所在的垂直网格线
grid-column-end属性:右边框所在的垂直网格线
grid-row-start属性:上边框所在的水平网格线
grid-row-end属性:下边框所在的水平网格线
这里我们注意看前面第一幅图中的标线,我们如果要把单元格放在第一格的位置,那就要放在水平网线1,和水平网格线2的中间。(垂直同理)
这里除了直接使用网格的数字之外,我们还可以使用网格线的名称。(就是上文定义的,这里派上了用场)
不仅如此,这里还有一个span关键字,代表左右边框之间跨越了几个网格。grid-column-start: span 2和grid-column-end: span 2的效果完全一致,有了这个写法,我们可以来固定一条边,然后通过跨越几个单元格的方式来计算出另外一条边的位置。
2.grid-column和grid-row
上面四个属性的合并缩写模式,值得一提的是,这里中间要用/号进行分隔。
.item {
grid-column: 1 / 2;
grid-row: 1 / 2;
}
/* 等同于 */
.item {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 2;
}
值得注意的是,斜杠后面的数字是可以省略的,默认为一个网格。
3.grid-area
用于指定项目放在哪一个区域,我们可以直接这样写:
item {
grid-area: a;
}
这样item就被放到了上面定义的a区域里面,不仅如此,他还可以看做grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写,直接指定项目位置。
grid-area: <row-start> / <column-start> / <row-end> / <column-end>
4.z-index
上面说了那么多的位置放置属性,那么肯定会导致位置重叠的问题,我们使用z-index来控制重叠的顺序。
5.justify-self、align-self和place-self
justify-self:设置单元格内容的水平位置(跟justify-items属性的用法一致,但只作用于单个项目)
align-self:设置单元格内容的垂直位置(跟align-items属性的用法一致,也是只作用于单个项目)
.item {
justify-self: stretch | start | end | center;
align-self: stretch | start | end | center;
}
- stretch:拉伸,占满单元格的整个宽度(默认值)
- start:对齐单元格的起始边缘
- end:对齐单元格的结束边缘
- center:单元格内部居中
place-self是align-self和justify-self的合并简写形式。
place-self: <align-self> <justify-self> /* 如果两个值相等则可以省略第二个值。*/