在前端开发中,创建灵活且响应式的布局是非常重要的。为了实现这一目标,Grid 网格布局成为了一种强大的工具。它提供了一种直观且灵活的方式来构建网页布局,本文将从Grid的基本概念入手,介绍Grid网格布局中的常用属性和功能。那么下面我们一起来探索这个强大且灵活的布局方式吧!
Flex与Grid
- Flex布局是一维的排版方式,也就是说一次只能控制一个方向(水平方向或者垂直方向),如果需要控制另一个方向需要再添加一层flexbox容器。
- Grid布局是二维的排版方式,一次能控制两个方向,通过将容器分成行和列,便可定义容器内元素的位置。
基本概念
行与列的概念(row & column)
- 水平区域------行
- 垂直区域------列
单元格(cell)
- 行和列交叉的区域就为一个单元格
- 正常情况下,n行和m列产生m*n个单元格->5行5列=5*5=25个单元格
网格线(grid line)
-
划分网格的线,称为"网格线"(grid line)。
-
水平网格线划分出行,垂直网格线划分出列。
-
正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线。
比如下图5行5列的情况下,有6根水平网格线和6根垂直网格线。
启用Grid布局
首先需要准备一个容器元素
html
<div class="container"></div>
然后设定容器的display:grid
即可
css
.container {
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
}
❕注:Grid布局分为display:grid
与display: inline-grid
,grid
下容器元素都是块级元素,而inline-grid
则是行内元素。
行高与列宽(grid-template-rows/columns
)
grid-template-rows
属性:定义每一行的行高grid-template-columns
属性:定义每一列的列宽
比如,下面将grid-template-rows
与grid-template-columns
都设定为5个100px
,中间用空格隔开,grid-template-rows
代表垂直方向 分割出5个高度为100px
的空间,grid-template-columns
代表水平方向 分割出5个高度为100px
的空间。
css
.container {
display: grid;
grid-template-rows: 100px 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px 100px 100px;
width: 500px;
height: 500px;
border: 1px solid rgb(0, 0, 0);
background-color: #eee;
}
repeat()
函数
如果觉得定义行高(grid-template-rows
)以及列宽(grid-template-columns
)的时候重复书写某个值很麻烦,那么就可以考虑使用repeat()
函数。
语法:
repeat(<length>, [<value> | <mode>])
- 参数1
length
:需要重复的次数 - 参数2
[<value> | <mode>]
:需要重复的值,可以是百分比、具体的值或者是某种模式
比如上面的定义行高与列宽中的代码就可以改写为下面这样
css
.container {
display: grid;
grid-template-rows: repeat(5, 100px);
grid-template-columns: repeat(5, 100px);
width: 500px;
height: 500px;
border: 1px solid rgb(0, 0, 0);
background-color: #eee;
}
repeat()
可以和正常的设定值混用
css
grid-template-rows: 100px repeat(2, 100px 100px);
fr
关键字
如果想按照比例分配行高(grid-template-rows
)以及列宽(grid-template-columns
)的值,那么就可以使用fr
关键字(Fraction,意为"片段")。
fr
表示比例,1fr
表示占1份。- 如果将上面的
grid-template-rows: repeat(5, 100px)
改为grid-template-rows: repeat(5, 1fr)
,即表示即各占5分之1的空间。 fr
关键字同样可以和正常的设定值混用
css
grid-template-rows: 1fr repeat(2, 1fr 1fr);
auto-fill
关键字
有时,单元格的大小是固定的,但是容器的大小不确定。
如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill
关键字表示自动填充。
css
grid-template-columns: repeat(auto-fill, 100px);
上面代码表示每列宽度100px
,然后根据容器的宽度自动填充,直到容器不能放置更多的列。
HTML:
html
<div class="container">
<div class="number cell1">1</div>
<div class="number cell2">2</div>
<div class="number cell3">3</div>
<div class="number cell4">4</div>
<div class="number cell5">5</div>
<div class="number cell6">6</div>
<div class="number cell7">7</div>
<div class="number cell8">8</div>
<div class="number cell9">9</div>
</div>
CSS:
css
.container {
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: repeat(5, 100px);
grid-template-columns: repeat(auto-fill, 200px);
}
.cell1 {
background-color: blue;
}
.cell2 {
background-color: yellow;
}
.cell3 {
background-color: orange;
}
.cell4 {
background-color: black;
color: white;
}
.cell5 {
background-color: #c077af;
}
.cell6 {
background-color: #f8d29d;
}
.cell7 {
background-color: #b4a87f;
}
.cell8 {
background-color: #d0e4a8;
}
.cell9 {
background-color: #4dc7ec;
}
效果图:
auto
关键字
auto
关键字可以让浏览器自己决定长度。
css
grid-template-columns: 100px auto 100px;
上面的意思是,第二列的宽度,等于该列单元格的最大宽度。
HTML:
html
<div class="container">
<div class="number cell1">1</div>
<div class="number cell2">2</div>
<div class="number cell3">3</div>
<div class="number cell4">4</div>
</div>
CSS:
css
.container {
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: repeat(5, 100px);
grid-template-columns: 100px auto 100px;
}
效果图:
❕注:除非单元格内容设置了min-width
,且这个值大于最大宽度。
指定元素的位置
下面给容器添加两个元素,设置对应的背景色
HTML:
html
<div class="container">
<div class="number cell1">1</div>
<div class="number cell2">2</div>
</div>
CSS:
css
.container {
width: 500px;
height: 500px;
display: grid;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: 100px 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px 100px 100px;
}
.number {
display: flex;
align-items: center;
justify-content: center;
box-sizing: content-box;
border: 1px solid rgb(117, 117, 117);
border-radius: 5px;
box-shadow: 0px 5px 3px #000;
font-size: 35px;
font-weight: 800;
}
.cell1 {
background-color: blue;
}
.cell2 {
background-color: yellow;
}
效果如图所示:
这个是默认没有定义元素位置的情况,如果想要指定元素位置需要用到grid-row
与grid-column
属性。
grid-row
与grid-column
grid-row
与grid-column
本身是复合属性。
-
grid-row
指定**垂直方向**上的范围 -
grid-column
指定**水平方向**上的范围 -
grid-row
属性的组成部分:grid-row-start
:上边框所在的水平网格线grid-row-end
:下边框所在的水平网格线
-
grid-column
属性的组成部分:grid-column-start
:左边框所在的垂直网格线grid-column-end
:右边框所在的垂直网格线
如果想使用grid-row
,首先指定grid-row-start
,然后再指定grid-row-end
即可,语法如下:
css
.cell-1 {
grid-row: <start-line> / <end-line>
}
gird-column
也是如此,也是先指定grid-column-start
,然后再指定grid-column-end
,语法如下:
css
.cell-1 {
grid-column: <start-line> / <end-line>;
}
有了这些前置知识后,现在就可以指定元素的位置了,打个比方,如果想占据让蓝色占据以及黄色占据下图所示的区域
首先来看蓝色的色块:
- 水平方向上的范围是从1到3,对应的
grid-column
的值为1 / 3
- 竖直方向上的范围是1到4,对应的
grid-row
的值为1 / 4
然后看看黄色的色块:
- 水平方向上的范围是从3到6,对应的
grid-column
的值为3 / 6
- 竖直方向上的范围是4到6,对应的
grid-row
的值为4 / 6
写出对应的CSS,看看效果:
css
.cell1 {
background-color: blue;
grid-column: 1 / 3;
grid-row: 1 / 4;
}
.cell2 {
background-color: yellow;
grid-column: 3 / 6;
grid-row: 4 / 6;
}
grid-area
(复合属性)
除了可以用grid-column
与grid-row
指定元素的位置,还可以使用grid-area
属性。
- 该属性为
grid-column
与grid-row
的复合属性
我们直接上代码:
css
.cell2 {
background-color: yellow;
/* grid-column: 3 / 6;
grid-row: 4 / 6; */
grid-area: 4 / 3 / 6 / 6;
}
效果和原本的是一样的,grid-area
的设置顺序是:
grid-row
的第一个值grid-column
的第一个值grid-row
的第二个值grid-column
的第二个值
可以理解为"坐标",即左上角、右下角坐标。
不过个人不太喜欢用,因为没有grid-row
与grid-column
看上去直观。
span
关键字
grid-row
和grid-column
的设定值是由第几至第几,比如第1至第5:1 / 5
实际在开发过程中是不会有之前图片上那样的标尺的,一遍一眼就可以看出对应的编号的。
因此Grid布局提供了span
关键字,span
是延伸的意思,所以可以理解为:
- 第几开始延伸多少格
所以我们可以将蓝色块的代码修改为下面这样:
css
.cell1 {
background-color: blue;
grid-column: 1 / span 3;
grid-row: 1 / span 2;
}
- 这里的
grid-column
意为:从1向后延伸3格 - 这里的
grid-row
意为:从1向后延伸2格
效果如下图:
给网格线(grid line)起别名
实际上我们可以给**网格线(grid line)**起别名,代码如下:
css
.container {
display: grid;
grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
width: 500px;
height: 500px;
border: 1px solid rgb(0, 0, 0);
background-color: #eee;
}
对应的代码中也可以使用别名了
css
.cell1 {
background-color: blue;
grid-column: X1 / X6;
grid-row: Y2 / Y4;
}
给单元格起别名(grid-template-areas
)
- 使用
grid-template-areas
就可以给单元格起别名
首先我们继续给容器增加两个元素
HTML:
html
<div class="container">
<div class="number cell1">1</div>
<div class="number cell2">2</div>
<div class="number cell3">3</div>
<div class="number cell4">4</div>
</div>
CSS:
css
.cell1 {
background-color: blue;
}
.cell2 {
background-color: yellow;
}
.cell3 {
background-color: orange;
}
.cell4 {
background-color: black;
color: white;
}
效果图:
现在通过grid-template-areas
给容器的各个单元格命名,构建出一个经典的网页布局吧!
css
.container {
width: 500px;
height: 500px;
display: grid;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
grid-template-areas:
"h h h h h"
"n m m m m"
"n m m m m"
"n m m m m"
/* 写点可以忽略该格子 */
". f f f ."
;
}
现在对容器中的元素使用grid-area
属性,并指定对应grid-template-areas
中为方格起的别名即可实现自动填充无需再传入坐标了!
css
.cell1 {
background-color: blue;
grid-area: h;
}
.cell2 {
background-color: yellow;
grid-area: n;
}
.cell3 {
background-color: orange;
grid-area: m;
}
.cell4 {
background-color: black;
color: white;
grid-area: f;
}
❕注意:repeat()
不适用于grid-template-areas
中。
行间距与列间距(grid-row/column-gap
)
如果觉得所有元素紧贴在一起不太好,Grid布局还提供了grid-row-gap
与grid-column-gap
来增加元素间的行间距与列间距
grid-row-gap
属性设置行与行的间隔(行间距)grid-column-gap
属性设置列与列的间隔(列间距)
下面我们将刚才写的经典布局的案例的CSS加上这两个属性
css
.container {
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
grid-template-areas:
"h h h h h"
"n m m m m"
"n m m m m"
"n m m m m"
/* 写点可以忽略该格子 */
". f f f ."
;
row-gap: 10px;
column-gap: 10px;
}
可以看到内部增加了列间距与行间距后将容器撑大了,所以容器的宽高也需要修改下:
css
.container {
display: grid;
/* width: 500px;
height: 500px; */
width: 540px;
height: 540px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
grid-template-areas:
"h h h h h"
"n m m m m"
"n m m m m"
"n m m m m"
/* 写点可以忽略该格子 */
". f f f ."
;
row-gap: 10px;
column-gap: 10px;
}
现在看上去就正常了!
grid-auto-flow
关键字
-
Grid布局提供了
grid-auto-flow
用于控制容器内元素的排列方向(类似Flex布局中的flex-direction
+flex-warp:warp
的效果) -
默认值为
row
,默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。 -
设置为
column
时,表示"先列后行",即先填满第一列,再开始放入第二列,具体参考下图数字的排列顺序。
设置单元格中的元素/内容的位置
justify-items
与align-items
justify-items
属性设置单元格内容的水平位置(左中右)。align-items
属性设置单元格内容的垂直位置(上中下)。
可选值:
-
start
:对齐单元格的起始边缘。 -
end
:对齐单元格的结束边缘。 -
center
:单元格内部居中。 -
stretch
:拉伸,占满单元格的整个宽度(默认值)。
比如现在想让容器中元素的编号向左上角对齐可以这么写:
CSS:
css
.number {
/* display: flex;
align-items: center;
justify-content: center; */
display: grid;
justify-items: start;
align-items: start;
box-sizing: content-box;
border: 1px solid rgb(117, 117, 117);
border-radius: 5px;
box-shadow: 0px 5px 3px #000;
font-size: 35px;
font-weight: 800;
}
效果:
place-items
(复合属性)
-
该属性为
justify-items
与align-items
的复合属性 -
语法
xmlplace-items: <align-items> <justify-items>;
比如刚才的代码就可以简写为:place-items: start start;
justify-self
与align-self
justify-self
属性设置单元格内容的水平位置(左中右),与justify-items
用法完全一致,但只作用于单个元素。align-self
属性设置单元格内容的垂直位置(上中下),与align-items
用法完全一致,但只作用于单个元素。
比如只想要第二个元素向左下角对其,就可以这么写:
CSS:
css
.cell1 {
background-color: yellow;
align-self: start;
justify-self: start;
}
效果:
place-self
(复合属性)
-
该属性为
align-self
属性和justify-self
属性的复合属性。 -
语法:
cssplace-self: <align-self> <justify-self>;
所以刚才的代码可以简写为这样:place-self: end end;
设置整个容器中内容的位置
justify-content
与align-content
justify-content
属性是整个内容区域在容器里面的水平位置(左中右)。align-content
属性是整个内容区域的垂直位置(上中下)。
取值:
注:下面的图都以justify-content属性为例
CSS:
css
.container {
display: grid;
width: 600px;
height: 600px;
background-color: #eee;
border: 1px solid rgb(0, 0, 0);
grid-template-rows: repeat(5, 100px);
grid-template-columns: repeat(5, 100px);
grid-auto-flow: row;
}
-
start - 对齐容器的起始边框。 默认值
-
end - 对齐容器的结束边框。
-
center - 容器内部居中。
-
stretch - 项目大小没有指定时,拉伸占据整个网格容器。
移除
grid-template-rows
以及grid-template-columns
后 -
space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
-
space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。
-
space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
place-content
(复合属性)
-
该属性是
align-content
和justify-content
的复合属性 -
语法:
cssplace-content: <align-content> <justify-content>
注意:如果省略第二个值,浏览器就会假定第二个值等于第一个值。
练习小游戏
GRID GARDEN-链接