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有多么简单