Grid Layout 入门

Grid Layout,即网格布局是 CSS3 新属性,可以轻松实现二维布局。随着近一年各大浏览器对该属性的支持,Grid 布局的呼声也越来越高。

最开始了解到 Grid 我是无感的,我无脑地把二维网格联想为 excel 表格,一个 excel 能玩儿出多大的花样?

直到有一天看到这个:

我靠,这不是轻松实现了页面布局?

有点儿意思。

1. Grid 基础结构

与 Flexbox 类似,Grid 布局需要用 display: grid 来声明一个容器(以下称为“网格容器”),该容器里的所有子元素自动成为网格项目(以下称为“网格项目”)。

1
2
3
4
5
6
<div class="grid-container">
<div class="grid-item"></div>
<div class="grid-item"></div>
...
<div class="grid-item"></div>
</div>
1
2
3
.grid-container {
display: grid;
}

2. Grid 常用属性

2.1 行与列

  • grid-template-columns 指定每列的宽度
  • grid-template-rows 指定每行的高度
  • grid-gap 指定列(或行)的间距

举个栗子:

1
2
3
4
5
.grid-container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 5px;
}

grid-gap 为每个网格项目之间添加 5px 的间隙。

fr 单位(fraction)是根据网格容器计算的单位列宽。我们在容器中设置了 grid-template-columns 属性值为 1fr 2fr 1fr,是将整个容器等分了 4(1+2+1) 列,因此容器的最小(单位)列宽为容器的 1/4 宽。同时,因为属性值有三个值,因此,默认每行显示三个元素,宽度比分别为 1: 2: 1。

当然,更为普遍的单位,例如 pxemrem和百分比同样可以使用,并且可以在 grid-template-columnsgrid-template-rows 属性中混合使用,例如:

1
grid-template-columns: 100px 3em 40%;

如果上述单位与 fr 同时设置为属性值,则 fr 在剩余空间再进行分割。举个栗子:

1
grid-template-columns: 50px 1fr 2fr 50px;

左右分别为 50px,剩余部分再以 1:2 的比例进行分割。

2.2 网格线与合并单元格

  • grid-area 应用于网格项目,起始行的网格线位置/结束行的网格线位置/起始列的网格线位置/结束列的网格线位置

  • grid-rows 应用于网格项目,起始行的网格线位置/结束行的网格线位置

  • grid-rows-start 应用于网格项目,起始行的网格线位置
  • grid-rows-end 应用于网格项目,结束行的网格线位置

  • grid-columns 应用于网格项目,起始列的网格线位置/结束列的网格线位置

  • grid-columns-start 应用于网格项目,起始列的网格线位置
  • grid-columns-end 应用于网格项目,结束列的网格线位置

举个栗子:

1
2
3
4
5
6
7
<div class="grid-container">
<div class="grid-item header"></div>
<div class="grid-item sidebar"></div>
<div class="grid-item"></div>
...
<div class="grid-item"></div>
</div>
1
2
3
4
5
6
7
8
.header {
grid-column: 1 / 4;
}

.sidebar {
height: 300px;
grid-row: 2 / 4;
}

这里涉及到一个很重要的概念——网格线。网格线用来在水平和垂直方向分割网格的线。水平方向的网格线是从左向右,垂直方向是从上往下,编号从 1 开始。

在本例中,网格线的位置如下:

注意:这里的网格线编号是以最初的状态来标号的,因此在这个例子中,垂直方向并不存在 line5,这是因为你看到的第 5 条线是由合并单元格被挤下来的元素生成的.

这样很容易理解 grid-column: 1 / 4grid-row: 2 / 4 轻松实现了我们常见的导航 header 和侧边栏 sidebar。

grid-columns
grid-rowsgrid-area 指定的起始位置与结束位置均指的是网格线的编号。几个属性之间的关系如下:

1
2
3
4
grid-columns: grid-column-start/grid-column-end;
grid-rows: grid-row-start/grid-row-end;

grid-area: grid-row-start/grid-column-start/grid-row-end/grid-column-end;

grid-columngrid-row 是一种简写的方法,分开来写等价于:

1
2
3
4
5
6
7
grid-columns: 1 / 4;
grid-column-start: 1;
grid-column-end: 4;

grid-row: 2 / 4;
grid-row-start: 2;
grid-row-end: 4;

另一种写法也可以实现相同的效果,以下写法是完全等价的:

1
2
3
4
5
grid-column: 1 / 4;
grid-column: 1 / span 3;

grid-row: 2 / 4;
grid-row: 2 / span 2;

span 关键字很像我们操作 excel 中的合并单元格,grid-column: 1 / span 3; 代表从第一列开始,合并 3 个单元格,也就是列网格线跨度为 3。grid-row: 2 / span 2; 代表从第 2 根网格线开始,横跨 2 个网格线。

2.3 负的网格线编号

网格线不仅可以从左到右(水平方向)、从上到下(垂直方向)编号,还可以反向编号,这时的编号是负数。

在上面的例子中,负编号如下:

因此,以下两种写法是等价的:

1
2
grid-column: 1 / 4;
grid-column: -1 / -4;