先看思维导图
起步
首先搭好基本的结构
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
<div class="item item-10">10</div>
<div class="item item-11">11</div>
<div class="item item-12">12</div>
<div class="item item-13">13</div>
<div class="item item-14">14</div>
<div class="item item-15">15</div>
<div class="item item-16">16</div>
</div>
这里我觉得一个问题是,grid
布局下面的所有元素都是同等的,实际中可能还存在层级的关系,直接使用略微有不满足语义化的缺陷,当然开发者是可以自己组建层级,然后再针对每个层级继续布局下去的 。
给每个项目设置样式以区分
.item {
font-size: 1em;
text-align: center;
}
.item-1 {
background-color: #b71c1c;
}
.item-2 {
background-color: #c2185b;
}
.item-3 {
background-color: #8e24aa;
}
.item-4 {
background-color: #651fff;
}
.item-5 {
background-color: #1a237e;
}
.item-6 {
background-color: #2196f3;
}
.item-7 {
background-color: #039be5;
}
.item-8 {
background-color: #18ffff;
}
.item-9 {
background-color: #009688;
}
.item-10 {
background-color: #00c853;
}
.item-11 {
background-color: #b2ff59;
}
.item-12 {
background-color: #eeff41;
}
.item-13 {
background-color: #fbc02d;
}
.item-14 {
background-color: #ff6f00;
}
.item-15 {
background-color: #e65100;
}
.item-16 {
background-color: #6d4c41;
}
然后开始了,先把容器设为display: grid
我们看到每个项独占一行,因为默认是块级元素,如果想变为行内,要设置display: inline-grid
,厂商前缀自己按照浏览器加上,我使用的是Chrome,不需要。
这两个设置跟flex
、inline-flex
是相似的。
接下来就见真格了,以下先是设置网格布局容器上的属性。
grid-template-columns, grid-template-rows
可以看到如果不给每个项设置宽高就根本没法看,所以第一步要设置grid-template-columns
和grid-template-rows
。
数值
#container {
display: grid;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
也可以使用百分比
#container {
display: grid;
grid-template-columns: 25% 25% 25% 25%;
grid-template-rows: 100px 100px 100px 100px;
}
看看如果设置的配置和实际元素数量不一致会怎么办
#container {
display: grid;
grid-template-columns: 25% 25% 25%;
grid-template-rows: 100px 100px 100px;
}
如果是
#container {
display: grid;
grid-template-columns: 25% 25%;
grid-template-rows: 100px 100px 100px;
}
如果是
#container {
display: grid;
grid-template-columns: 25% 55%;
grid-template-rows: 50px 100px 200px;
}
如果把方向从row变为column
#container {
display: grid;
grid-auto-flow: column;
grid-template-columns: 25% 25%;
grid-template-rows: 100px 100px 100px;
}
可以得出结论就是前面row * col个元素是遵循设置内容,然后按照排列次序以及排列方向,延续row或者column的设置值。
repeat()
这个函数为懒人设置,表示重复多少次
#container {
display: grid;
grid-template-columns: repeat(3, 25%) 100px;
grid-template-rows: repeat(2, 100px) repeat(2, 150px);
}
repeat()
里第二个参数还能指定多个项
#container {
display: grid;
grid-template-columns: repeat(2, 15% 25%);
grid-template-rows: repeat(2, 100px 150px);
}
第一个值也可以不指定具体的数字,而用auto-fill
表示尽量排下去,有点float
的味道,此时不能确定另一个维度的设置会用到几个。
#container {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
grid-template-rows: 50px 100px 150px 200px 250px; /*不知道可能用到几个 */
}
此时我把浏览器拉宽,排下来只有三行了,就只会用到grid-template-rows
里的三项值。
fr
这个关键字就相当于flex布局里的flex-grow
,表示各元素之间的比例。
#container {
display: grid;
grid-template-columns: 1fr 2fr 3fr 4fr;
grid-template-rows: 50px 100px 150px 200px;
}
配合绝对数值也是和flex里一样的
#container {
display: grid;
grid-template-columns: 1fr 2fr 3fr 100px;
grid-template-rows: 50px 100px 150px 200px;
}
minmax()
这个函数就类比于设置min-width
和max-width
。下面我设置了个特殊情况,就是最小值要比最大值还来的大。
#container {
display: grid;
grid-template-columns: 1fr 1fr minmax(500px, 1fr) 1fr;
grid-template-rows: 50px 100px 150px 200px;
}
此时500px
是大于1fr
的,我们看到
说明此时布局系统优先满足最小值的设定。
auto
auto
关键词表示接盘,它就是一个接盘侠——把剩下的空间都分给我。
#container {
display: grid;
grid-template-columns: 1fr 1fr auto 1fr;
grid-template-rows: 50px 100px 150px 200px;
}
#container {
display: grid;
grid-template-columns: 100px 100px auto auto;
grid-template-rows: 50px 100px 150px 200px;
}
网格线名称
在这里还能指定网格线的名称,但此时还排不上用场,注意实际的网格线数要+1,四个格子就要有五根线。
#container {
display: grid;
grid-template-columns: [no1] 100px [no2] 100px [no3] 100px [no4] 100px [no5];
grid-template-rows: 50px 100px 150px 200px;
}
grid-row-gap,grid-column-gap,grid-gap
它们用来设置网格之间的间隙,一般在网格布局中都会有这项设置,下图是antd
的网格组件
#container {
display: grid;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
grid-row-gap: 20px;
grid-column-gap: 10px;
/* 或者
grid-gap: 20px 10px;
*/
}
grid-template-areas
这个属性和刚才指定网格线类似,它是给区块指定名字,比如
#container {
display: grid;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
grid-template-areas:
"caocao caocao zhaoyun machao"
"caocao caocao zhaoyun machao"
"guanyu guanyu zhangfei zhangfei";
}
如果某个区块不需要名字,可以指定.
。
注意设置了区域名字后,区域两边的线会被自动命名,比如caocao的起始位置的水平网格线和垂直网格线叫做caocao-start,终止位置的水平网格线和垂直网格线叫做caocao-end。
grid-auto-flow
这个属性用来指定网格是先横向排列还是先纵向排列,跟flex布局里的flex-direction
类似。
#container {
display: grid;
grid-auto-flow: column;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
这个属性上还能设置dense
,要用一个具体的例子来说明这个属性的作用。
假设我们在1和2上设置宽度
#container {
display: grid;
grid-auto-flow: row;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
.item {
font-size: 1em;
text-align: center;
}
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
background-color: #b71c1c;
}
.item-2 {
grid-column-start: 1;
grid-column-end: 3;
background-color: #c2185b;
}
此时的效果是
由于区块2另起了一行,区块1的一行都被空着,如果设置
#container {
display: grid;
grid-auto-flow: row dense;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
没有比见缝插针这个词更适合当前的场景了。
justify-items,align-items,place-items
justify-items
针对单元项里的内容的水平位置,align-items
针对单元项里的内容的垂直位置,它们都能取如下的值
- start
- end
- center
- stretch
设置成end
看看效果
#container {
display: grid;
justify-items: end;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
place-items
就是justify-items
和align-items
的组合。
justify-content, align-content, place-content
justify-content
是单元项在容器里的水平位置,align-content
是单元项在容器里的垂直位置,它们可以取如下的值
- start
- end
- center
- stretch
- space-around
- space-between
- space-evenly
让人想起了flex布局。
也试两个看看
#container {
display: grid;
justify-content: space-around;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
}
改成end
同理place-content
也是justify-content
和align-content
的组合。
grid-auto-columns,grid-auto-rows
它们用来指定超出范围的那些单元项的设置,之前我们已经试过超出设置范围的单元项是什么样子的,用这两个配置能对它们多一层控制,比如
#container {
display: grid;
grid-template-columns: 25% 25% 25%;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
超出3 * 3 = 9个范围之后,多出来的单元项,将它们的高度设置为50px,可以将下图和上面的例子对比一下。
对于那些设置了位置,使之不在grid-template-columns
和grid-template-rows
范围之内的单元项(比如设置grid-column-start
、grid-column-end
),也被这两个配置影响。
grid-template, grid
跟flex一样,这两个也是合并的设置,反正我是记不住的
grid-template
= grid-template-column
+ grid-template-rows
+ grid-template-areas
grid
= grid-template-rows
+ grid-template-columns
+ grid-template-ares
+ 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
它们用来设置行的起点、终点和列的起点、终点,注意CSS里的起点都是以1开始的。
修改第一个单元项
.item-1 {
background-color: #b71c1c;
grid-column-start: 2;
grid-column-end: 5;
}
针对这第一个单元项,还能再狠一点
.item-1 {
background-color: #b71c1c;
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 4;
}
可见是先把单元项1给排好,然后其他的依次按照grid-auto-flow
的配置来排列。
另外刚才指定的网格线名称也能在这里使用了。
.item-1 {
background-color: #b71c1c;
grid-column-start: no2;
grid-column-end: no5;
}
也能使用span
来简单的指定跨越几个单元格。
.item-1 {
background-color: #b71c1c;
grid-column-start: span 2;
}
或者
.item-1 {
background-color: #b71c1c;
grid-column-start: no2;
grid-column-end: span 2;
}
grid-column
和grid-row
是以上的合并简写。比如
.item-1 {
background-color: #b71c1c;
grid-column: 1 / 3;
/* 与以下相等
grid-column-start: 1;
grid-column-end: 3;
*/
/* 与以下相等
grid-column: 1 / span 2;
*/
}
grid-area
grid-area
就会用到刚才指定的区块名字,比如刚才曾经指定
#container {
display: grid;
grid-template-columns: [no1] 100px [no2] 100px [no3] 100px [no4] 100px [no5];
grid-template-rows: 100px 100px 100px 100px;
grid-template-areas:
"caocao caocao zhaoyun machao"
"caocao caocao zhaoyun machao"
"guanyu guanyu zhangfei zhangfei";
}
现在可以设置第一个区块为
.item-1 {
background-color: #b71c1c;
grid-area: caocao;
}
那最终第一个区块就占据了名字为caocao的区域
当然也能用数字来指定
.item-1 {
grid-area: 1 / 1 / 3 / 3;
}
justify-self, align-self, place-self
这几个跟flex布局里的align-self
很相似,都是调整单元项在父级容器里的位置。
justify-self
调整单元项在父级容器里的水平位置,align-self
调整单元项在父级容器里的垂直位置,place-self
理所当然是它们的合并方式,可以取如下的值
- start
- end
- center
- stretch
最后做一个综合的例子——华容道
选用最傻瓜的方式——指定grid-area
<!DOCTYPE html>
<html>
<head>
<title>华容道</title>
<style>
#container {
display: grid;
grid-template-columns: 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px 100px;
grid-template-areas:
"zhaoyun caocao caocao huangzhong"
"zhaoyun caocao caocao huangzhong"
"zu1 machao . zu2"
"zu3 machao . zu4"
"guanyu guanyu zhangfei zhangfei";
}
.item {
font-size: 1em;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.item-1 {
background-color: #b71c1c;
grid-area: zhaoyun;
}
.item-2 {
background-color: #c2185b;
grid-area: caocao;
}
.item-3 {
background-color: #8e24aa;
grid-area: huangzhong;
}
.item-4 {
background-color: #651fff;
grid-area: zu1;
}
.item-5 {
background-color: #651fff;
grid-area: zu2;
}
.item-6 {
background-color: #009688;
grid-area: zu3;
}
.item-7 {
background-color: #00c853;
grid-area: zu4;
}
.item-8 {
background-color: #2196f3;
grid-area: machao;
}
.item-9 {
background-color: #546e7a;
grid-area: guanyu;
}
.item-10 {
background-color: #e65100;
grid-area: zhangfei;
}
</style>
</head>
<body>
<div id="container">
<div class="item item-1">赵云</div>
<div class="item item-2">曹操</div>
<div class="item item-3">黄忠</div>
<div class="item item-4">卒</div>
<div class="item item-5">卒</div>
<div class="item item-6">卒</div>
<div class="item item-7">卒</div>
<div class="item item-8">马超</div>
<div class="item item-9">关羽</div>
<div class="item item-10">张飞</div>
</div>
</body>
</html>