1.前言
网格布局(Grid)是最强大的 CSS 布局方案。
它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。
他通过相应的属性指定该容器共有几行几列,每行每列的大小,就可以创建一个个网格,而他的子元素将依次放入这些表格中(一个网格对应一个子元素)。通过设定网格的大小,就能设置其子元素的大小和位置。
2.display: grid
使用网格布局时先在父容器中设置 display: grid,我们来看看基本效果
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
.container{
margin: 50px auto;
width:200px;
height:100px;
display: grid;
}
效果:
3.设定行和列的数量
前面的例子说明网格布局默认只有一行一列,可以通过下面的属性设定行和列的数量:
grid-template-columns:定义每一列的列宽,有几个值就表示有几列
grid-template-rows:定义每一行的行高,有几个值就表示有几行
设定为2行2列 每列各占50%的空间
.container{
margin: 50px auto;
width:400px;
height:400px;
border: 1px solid #333333;
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
}
为其设置3个子元素
<div class="container">
<div></div>
<div></div>
<div></div>
</div>
效果:
列宽和行宽除了使用百分比,还可以使用具体的像素值
这里设定为2列,每列宽度都是100px,而我们的容器有400px,也就是说这种设置会造成剩余空间的浪费,实际开发中我们不会这么做,这里只是演示
.container{
margin: 50px auto;
width:400px;
height:400px;
border: 1px solid #333333;
display: grid;
grid-template-columns: 100px 100px;
grid-template-rows: 50% 50%;
}
效果:
如果所有列宽加起来超过了容器宽度,多出部分则会溢出。但是我们一般不会这么设定,因为这样没什么意义。在设定列宽之前我们肯定先要计算好,避免这种情况发生。
.container{
margin: 50px auto;
width:400px;
height:400px;
border: 1px solid #333333;
display: grid;
/* 250+200 > 400 */
grid-template-columns: 250px 200px;
grid-template-rows: 50% 50%;
}
4.fr 关键字
实际开发中,我们有时候不希望每列每行的宽度写死,而是希望他自适应容器,这时候就可以用到 fr 关键字(fraction 的缩写,意为"片段"),他类似于flex布局的flex-grow属性,按比例占据容器的剩余空间
.container{
margin: 50px auto;
width:400px;
height:400px;
display: grid;
grid-template-columns: 100px 1fr 2fr;
border: 1px solid #333333;
}
这里设置成3列1行,第一列100px,第二列(1fr)和第三列(2fr)共享剩余的300px(400-100) ,按比例第二列(1fr)占据300/(1+2)1=100px,第三列(1fr)占据300/(1+2)2=200px
这里对代码进行修改,让容器的宽度不再写死,而是让他占满一行,通过缩放浏览器窗口的大小动态修改容器的宽度,看看效果
.container{
margin-top: 50px;
height:200px;
display: grid;
grid-template-columns: 100px 1fr 2fr;
border: 1px solid #333333;
}
可以看到,随着浏览器窗口大小的变化,第二列的宽度总是等于第三列的一半。而且第一列的宽度是写死的,第二列和第三列只能分配除他之外的剩余空间
5.auto 关键字
auto关键字表示由浏览器自己决定长度。
一个子元素的宽度由两部分组成,自身宽度和瓜分容器的剩余宽度(fr)
自身宽度分为2种:固定宽度和内容撑开。
如果容器放置完子元素的宽度后还有剩余,将尝试将剩余空间瓜分给设定了 fr 的子元素
通俗的说,auto关键字就是,如果没有剩余空间,或者存在剩余空间,到那时兄弟列中存在fr关键字,则该列的宽度由内容撑开
如果有剩余空间,且兄弟列中不存在fr关键字,则将容器剩余空间分给该列
auto与fr的区别:两者都有可能瓜分容器的剩余空间,但是fr优先级更高.
这里的容器有剩余空间,第二列的宽度设定为auto,他的兄弟列没有fr关键字,他将吸收容器剩余的空间
.container{
margin-top: 50px;
height:200px;
display: grid;
grid-template-columns: 100px auto 200px;
border: 1px solid #333333;
}
这里的容器没有剩余空间,该列的宽度由内容撑开(这个例子意义不大,因为容器溢出了,这里只是区分fx与auto的区别)
这里的容器虽然有剩余空间,但是他的兄弟列有fr关键字,他无法吸收剩余空间
grid-template-columns: 100px auto 1fr;
6.minmax()函数
minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
设定第一列最少100px,最大占据33%
.container{
margin-top: 50px;
height:200px;
display: grid;
/* 第1列最少100px,最大占据33% */
grid-template-columns: minmax(100px, 1fr) 1fr 1fr;
border: 1px solid #333333;
}
可以看到,当容器宽度大于300时,第一列的始终占据33%的容器宽度,而随之容器宽度的减小,小于300时,继续按按33%计算第一列的宽度将小于100,这时候设置的最小值100发生作用,第一列的宽度始终维持在100px
7.repeat()函数
如果要设置成10列,20列甚至更多的列,而这些列都有相同的宽度,就要写很多遍重复的值,这时,可以使用repeat()函数,简化重复的值。
语法:repeat(重复次数,要重复的值)
重复多个值时使用空格将每个值隔开
下面2种写法作用是一致的
.container{
margin-top: 50px;
height:200px;
display: grid;
grid-template-columns: 1fr 2fr 3fr 1fr 2fr 3fr;
border: 1px solid #333333;
}
.container{
margin-top: 50px;
height:200px;
display: grid;
grid-template-columns: repeat(2,1fr 2fr 3fr);
border: 1px solid #333333;
}
效果:
上面的例子中,因为每列的宽度是据比例来计算的,所以无论重复多少次,所有列的总宽度 = 容器宽度。
但是如果每列的宽度写死了,例如每列20%或者200px,在不知道容器具体宽度的情况下,我们无法得知该重复多少次,这时候可以使用auto-fill 关键字,这个关键字将自动换算成合适的重复此时.他将每一行(或每一列)容纳尽可能多的单元格
.container{
margin-top: 50px;
height:300px;
display: grid;
grid-template-columns: repeat(auto-fill,200px);
grid-template-rows: 33% 33% 33%;
border: 1px solid #333333;
}
当容器宽度发生变化,将自动调整重复次数来决定列数