乐趣区

10分钟理解CSS3 Grid

基本介绍
上一篇文章我们介绍了 css3 flexbox,今天我们再来说说 css3 的另外一个强大的功能:Grid。Grid 做前端的同学应该都很熟悉了,翻译成中文为“栅格”,用过 bootstrap、semantic ui、ant design 的同学肯定都了解 grid layout(删格布局),以往 css 框架中的 grid 布局一般是通过 float 和百分比的宽度实现的,这种实现有几种缺点:

html 不够简洁;
需要清除浮动以避免高度塌陷;
列的个数是固定的,不能灵活定义。比如 bootstrap 是 12 列,semantic ui 是 16 列,ant design 24 列。

当然 grid 也可以用 flex 实现,但是并不会比用 float 简单多少,而且 flex 擅长的是一维空间的布局,而对 grid 这种二维空间并不擅长。现在 css3 从规范和标准层面实现了 grid,编程体验大大提升!
兼容性

用法
Grid 作为一个二维的栅格系统,由若干列(column)和行(row)构成。
1. Column
(1) 设置 column
CSS3 中的 Grid 可以划分为任意个数的列(column),而且每个 column 的宽度可以任意设置!我们先来看一个简单的例子:
html:
<div id=”content”>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
css:
body{
color: #fff;
text-align: center;
}
#content{
display: grid;
grid-template-columns: 33.3% 33.3% 33.3%;
max-width: 960px;
margin: 0 auto;
}
#content div{
background: lightgrey;
padding: 30px;
}
#content div:nth-child(even){
background: skyblue;
}
效果:
当我们设置了 display: grid 和 grid-template-columns: 33.3% 33.3% 33.3% 后 #content 就被划分成了三行三列的 grid,此时#content 被称为 grid container,而 #content 的子元素称为 grid item。
我们也可以任意改变 column 的个数和宽度,比如:
#content{
grid-template-columns: 10% 20% 30% 40%;
}
效果:
(2) fr(fraction)
css3 中引入了一个新的单位 fr(fraction),中文意思为“分数”,用于替代百分比,因为百分比(小数)存在除不尽的情况,用分数表示可以避免多位小数的写法。比如三列等宽的 grid 可以表示为:
grid-template-columns: 1fr 1fr 1fr;
(3) repeat
我们也可以用 repeat 方法来简化 column 或者 row 的写法,repeat 方法接受两个参数,第一个参数表示重复的次数,第二个参数表示重复的内容。所以,三列等宽的 grid 我们还可以表示为:
grid-template-columns: repeat(3, 1fr);
当我们要定义的列数很多时,repeat 就会变得非常有用,比如我们要定义一个 10 列等宽的 grid,可以写成 repeat(10, 1fr),而不用将 1fr 重复书写 10 遍。
2. Row
(1) 设置 row
当我们设置 column 之后,row 会因为元素的换行而自动产生,但是我们依然可以设置 row 的个数和高度。
css:
#content{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, 60px);
max-width: 960px;
}
效果:
可以看到,虽然第四行没有内容,但是 row 确实存在并占据了那部分空间。
(2) minmax
上面的例子中我们给了 row 一个固定高度,这导致一个问题:如果某个 grid item 中的内容特别多,受制于固定的高度,部分内容将无法显示,如下图:

为解决这个问题,css 提供了 minmax 函数,让我们可以设置 row 的最小高度和最大高度,最大高度取 auto 后便可以让 row 的高度自适应:
css:
grid-auto-rows: minmax(60px, auto);
// 或者
grid-template-rows: repeat(3, minmax(60px, auto));
效果:
(3) grid gap
如果我们想给行和列之间加上间隔,也有现成的方法:css:
grid-gap:{
10px;
}
效果:
3. Grid Line
以上所有例子中,grid 中的每个 grid item 都是按默认顺序排列的。如果我们想重新布局改变 grid item 的位置或大小呢?为此引入了 grid lines 的概念,所谓的 grid lines 就是将 grid 若干等分后的分割线,如下图中横向和纵向序号 1~8 的线即为 grid lines:
<img src=”http://lc-jOYHMCEn.cn-n1.lcfi…; alt=”drawing” width=”500″/>
通过定义 grid item 的起始和结束的 grid line 我们就可以实现对 grid item 位置和覆盖面积的控制。一个简单的例子:
html:
<div id=”content”>
<div class=”one”>1</div>
</div>
css:
#content {
display: grid;
grid-template-columns: repeat(8, 100px);
grid-template-rows: repeat(8, 100px);
grid-gap: 10px;
}

.one {
grid-column-start: 3;
grid-column-end: 6;
grid-row-start: 3;
grid-row-end: 6;
}
效果:
通过设置 grid-column-start/end grid-row-start/end 相当于给 grid item 设置起始坐标和结束坐标,上面的 css 也可以简写为:
.one {
grid-column: 3 / 6;
grid-row: 3 / 6;
}
// 或者
.one {
grid-area: 3 / 3 / 6 / 6;
}
如果 grid item 的起始 grid line 为默认,我们可以只设置它的跨度(span):
.one{
grid-column: span 3;
grid-row: span 3;
}
4. Grid Area Template
除了通过 grid lines 进行布局,css3 提供了一种更牛逼的布局方式:grid area template。与其用语言解释什么是 grid area template,不如直接看代码:
html:
<div id=”content”>
<header>Header</header>
<main>Main</main>
<section>Section</section>
<aside>Aside</aside>
<nav>Nav</nav>
<footer>Footer</footer>
</div>
css:
body {
color: #fff;
text-align: center;
}

#content {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(100px, auto);
max-width: 960px;
margin: 0 auto;
grid-gap: 10px;
grid-template-areas:
“header header header header”
“aside . main main”
“nav . main main”
“section section section section”
“section section section section”
“footer footer footer footer”;
}

#content>* {
background: #3bbced;
padding: 30px;
}

header {grid-area: header;}
main {grid-area: main;}
section{grid-area: section;}
aside {grid-area: aside;}
nav {grid-area: nav;}
footer {grid-area: footer;}
效果:
看明白没有?重点在于 grid container 的 grid-template-areas 属性。我们给每个 grid item 设置一个 grid area,然后在 grid container 中设置一个 grid area 模版(grid-template-areas),模版中每行字符串表示一个 row,每个 area 名称表示一个 column,完全将几何布局用文字模拟出来,空白的 grid item 用 . 表示。当然使用 grid area 要注意语法严谨,像 “header main header main” 这种写法 css 是无法解析的,用 area 名称模拟出的结构在二维空间上必须是一个整体,因为每个 grid item 也是无法分割的。
使用 grid area template 的有点在实现响应式布局时也是显而易见的,我们只需要针对不同的屏幕尺寸制定不同的 grid area template 就行了。
5. Justify and Align
与 flex 类似,grid 也可以设置 justify 和 align 来调整 grid item 横向和纵向对齐方式。同样也同时支持对 grid container 或单个 grid item 进行设置。
对 grid container 设置
html:
<div id=”content”>
<div class=”one”>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
css:
#content {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, minmax(120px, auto));
grid-gap: 10px;
max-width: 960px;
align-items: start;
justify-items: end;
}
效果:
注意:flex 里面用的是 justify-content 而 grid 里面是 justify-items,flex 里面的值是 flex-start/flex-end,而 grid 里面是 start/end。justify 和 align 的默认值都是 stretch。
对 grid item 设置
css:
.one{
align-self: start;
justify-self: end;
}
效果:
实践
掌握了上述知识,我们就能用 CSS3 Grid 快速做出各种 layout 效果了,附上几个简单的 codepen 示例:

12 列 grid 布局
花瓣式布局
响应式布局

退出移动版