玩游戏学前端-贪吃蛇-Grid布局

CSS Grid网格布局


在贪吃蛇游戏中,我们使用了CSS中的Grid网格布局,如果不用Grid,你可以使用Canvas绘图。其实在其它编程语言的UI设计中,早已有此类布局方案,比如Java中的GridLayout,感觉CSS把后端语言的UI设计又重新走一遍,而且进展还比较慢 , 多年以前我们还只能使用position,float和各种骇客技术实现布局,直至出现Flex、Grid才真正意义上的解脱;

网格布局示例图


HTML结构


需要将想要控制的元素包装在父容器DIV中

1
2
3
4
5
6
<div class="wrapper">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
<div class="div4">4</div>
</div>

让我们为div添加一些样式,这样就可以轻松地区分不同盒子,这里使用了 display:grid,也就是网格布局

1
2
3
4
5
6
7
8
9
10
11
12
.wrapper > div {
background-color: orange;
border: 1px black solid;
}

.wrapper > div:nth-child(odd) {
background-color: indianred;
}

.wrapper{
display: grid
}

Grid-template-columns 和 Grid-template-rows


grid-template-columns 规则

对于grid网格布局,我们首先需要了解的是 grid-template-columns 和 grid-template-rows 这两条规则。这两条规则控制了网格的形状。这些规则的值可以是长度、百分比或网格中空闲空间的一部分。还可以将它们设置为auto,这样做将会填充div盒子的剩余的空间。看例子:

1
2
3
4
.wrapper{
display: grid;
grid-template-columns: 100px 100px 100px
}

上面代码片断中我们设置了三列,每列100px, 但是wrapper下有四个div,所以会有一个div换行显示, display的值还可以设置为inline-grid

修改一下中间设置为auto

1
2
3
4
.wrapper{
display: grid;
grid-template-columns: 100px auto 100px
}

上面代码中,中间值使用了auto, 那么中间那个div将填充所有剩余部分

也可以使用fr, 网格布局提供了fr(fraction片段的意思),它用于表示比例关系,如果列宽度都为1fr , 那么将平分此行

1
2
3
4
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}

上面代码中将一行分为四列,每列宽度一样

修改一下值

1
2
3
4
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr 3fr 1fr;
}

可以看出第二列是第一列的2倍,第三列的大小是前面二列的和; 试着修改最后一列的大小

grid-template-columns 和 grid-template-rows 规则
1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50px 50px;
}

上面定义二行二列,每一行的高度都为50px, 如果将第一个50px改成其它值如30px, 那么第一行高度将为30px

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: 100px 20px 250px;
grid-template-rows: 150px 40px;
}

上面定义二行三列,第一行高150px, 第二行高40px, 前面3个div成为一行中三列,最后一个div单独一行

grid-template 重复规则: Repeat

如果你的网格布局中有一个重复的元素,你可以使用repeat并告诉它重复多少次相同的元素。
例如,假设你有12个元素,你想让它们以相同的宽度水平放置。您可以在grid-template-column使用repeat(12, 1fr)。

也可以像下面这样

1
2
3
4
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr 5fr 10fr);
}

上面代码中重复4个div元素,1,2,3是第一部分,分别为1fr, 5fr, 10fr; 后续依此类推

Grid-auto-columns 和 Grid-auto-rows 规则

此规则帮助你设置网格单元格的宽度和高度。如果不设置此规则,网格的行和列将根据内容展开。

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
}

上面代码重复4个元素,因为总共有12个元素,所以拆分成了3行,每行100px高

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-auto-rows: 100px;
}

上面代码重复6个元素,因为总共有12个元素,所以拆分成了2行,每行100px高

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 20px 40px 60px;
}

minmax() 函数

网格自动规则的一个很好的特性是minmax函数。
只需将最小值设置为第一个参数,将最大值设置为第二个参数。如果将第二个参数设置为auto,则会得到响应式单元格大小。

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(50px, auto)
}

以上两个结果是CSS相同,div中内容不同的情况

Grid-gap


顾名思义,该规则在网格单元格之间创建了一个间隙(gap)。
如果你使用grid-gap: 5px,你会在每个单元格之间得到5px的间隙。或者,只能设置行或列间隙,分别为grid-row-gap: 5px和grid-column-gap: 5px。

1
2
3
4
5
6
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(50px, auto);
grid-gap: 5px;
}

子div元素规则


到目前为止,我们只关注网格的形状和在网格中流动的项。现在我们将学习如何单独控制每一项。

为了定位每一项,我们使用网格线作为参考。下面是2x4网格的行和列,分别用黑色和橙色表示。

使用带有行号的 grid-column 和 grid-row 规则来定位元素。

例如,如果我们为第一个子div设置grid-column: 1/3,它将使用网格中的前两个单元格, 也就是第1格到第3格,但不包含第3格, 这种做法类似于在Excel中的列合并。

grid-column属性是grid-column-start和grid-column-end的合并简写形式,grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。

1
2
3
4
5
6
7
8
9
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
grid-gap: 5px;
}
.div1{
grid-column: 1/3;
}

1
2
3
4
.div1 {
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
}
1
2
3
4
5
6
7
8
9
10
11
.div1  {
grid-column: 1 / 3; /*占用 1~2 列, 也就是跨列*/
grid-row: 1 / 2;
}
/* 等同于 */
.div1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}

再看下面示例,div1元素跨列和行

1
2
3
4
.div1{
grid-column: 1/3;
grid-row: 1/3;
}

也可以使用grid-arge

1
2
3
.div1{
grid-area: 2/2/3/4;
}

Grid-area 和 grid-template-areas


下面的示例稍复杂一点

1
2
3
4
5
6
7
8
<div class="wrapper">
<div class="header">页头</div>
<div class="leftCol">左侧</div>
<div class="rightCol">右侧</div>
<div class="midTop">中间上方</div>
<div class="midBottom">中间下方</div>
<div class="footer">页脚</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.header{
grid-area: header;
background-color: LightSeaGreen ;
}

.leftCol{
grid-area: leftCol;
background-color: orange;
}

.rightCol{
grid-area: rightCol;
background-color: lightblue;
}

.midTop{
grid-area: midTop;
background-color: lightgrey;
}

.midBottom{
grid-area: midBottom;
background-color: pink;
}

.footer{
grid-area: footer;
background-color: lightgreen;
}

.wrapper {
display: grid;
grid-template-columns: 1fr 4fr 4fr 1fr;
grid-template-rows: 50px 100px 100px 30px;
grid-template-areas:
"header header header header"
"leftCol midTop midTop rightCol"
"leftCol midBottom midBottom rightCol"
"footer footer footer footer";
grid-gap: 5px;
}

布局结果

如果想让页脚只取两列并居中,那么我只需在网格模板区域中用点(.)替换页脚的第一个和最后一个。

1
2
3
4
5
6
7
8
9
10
11
.wrapper {
display: grid;
grid-template-columns: 1fr 4fr 4fr 1fr;
grid-template-rows: 50px 100px 100px 30px;
grid-template-areas:
"header header header header"
"leftCol midTop midTop rightCol"
"leftCol midBottom midBottom rightCol"
". footer footer .";
grid-gap: 5px;
}

你需要grid


Grid 布局还有很多其它属性,可以参考官方文档, 有了上述基础,我们就可以画出贪吃蛇游戏的界面了,马上为你呈现使用Grid有多么简单