本文初次发表于CSDN:网格布局grid。为什么要将其转到掘金?今天向一个朋友推荐掘金的文章,他问我为什么不在CSDN上进行博客发表,"那里容易百度搜到、看到的人多......",他竟然没听过掘金,之后向他疯狂推荐了一波掘金,然后记起来我也尝试了一次CSDN使用(里面有很多高质量文章不否认,但是自己体验很是不好),50多个浏览除了这位朋友的,剩下都是我好奇想看看多少人看了我的博客而产生的,事实上并没有人看。对于这一点感觉掘金就好多了,不管怎样至少会让我的文章被其他小伙伴看到,所以想把这篇文章转到掘金。
1. 前言
对于CSS的grid布局也了解过一些,但一直没怎么用,多少有些生疏,借着仿去哪网的城市列表页,对这些技术进行一个综合的学习
注:本文主要参考MDN的网格布局,在目录上可能会有极大的相似,内容上相对MDN更加通俗易懂,案例围绕下方图的效果进行进行设计参考https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout
如需转载,请注明出处
效果如下
2. grid网格布局
2.1 网格容器
通过在元素上声明display:grid来创建一个网格容器,这个元素的所有直系子元素都会自动成为网格元素
2.2 网格轨道
行列设置
通过grid-template-columns和grid-template-rows属性可以在网格容器中定义网格的行和列,任意两条线之间的空间就是一个网格轨道,例如下方图中红色框中为一个行轨道,蓝色框中为一个列轨道
grid-template-columns可以定义列轨道的大小,即列的宽度
下方代码将.wrapper设置为网格容器,其直系子元素就变成了网格元素,通过grid-template-columns设置了三个相等的值将一行分为三列,每一列138px,这样网格中每一行中就有了三个网格元素
HTML
<div class="wrapper">
<div>北京</div>
<div>上海</div>
<div>三亚</div>
<div>香港</div>
<div>杭州</div>
<div>广州</div>
<div>成都</div>
<div>深圳</div>
<div>苏州</div>
<div>桂林</div>
<div>西安</div>
<div>厦门</div>
</div>
CSS
.wrapper{
display: grid;
grid-template-columns: 138px 138px 138px;
}
注:对于案例中其他样式的CSS代码如下,仅列出一次
.wrapper{
width: 414px;
background-color: #f5f5f5;
font-size: 12px;
margin: 0 auto;
border: 1px solid #00bcd4;
}
.wrapper > div{
box-sizing: border-box;
line-height: 44px;
border: 1px solid #00bcd4;
border-radius: 10px;
}
效果
fr单位
在网格布局中,还为我们提供了一个新的单位fr,这是一个相对的单位,上面的138px是我们写死的长度,如果网格容器的宽度是变化的,我们就不能保证每行的3个元素刚好可以占满容器
将CSS代码改为
.wrapper{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
这样表示在网格容器中有三列,每一列各占一份
效果还是不变的
将CSS代码改为
.wrapper{
display: grid;
grid-template-columns: 1fr 2fr 1fr;
}
这样表示中间那一列的网格元素占两份,左右两边的网格元素占一份
效果为
fr单位,我们可以很容易做到按照一定的比例去设置每一列
repeat()
网格系统还提供给我们一个更加方便的函数 它到底有什么用,先写代码来看看
.wrapper{
display: grid;
grid-template-columns: repeat(3,1fr);
}
第一个参数表示重复的次数,第二个就是份数,这个跟上面写的grid-template-columns: 1fr 2fr 1fr;是相同的效果,这样如果我们有更加复杂的需要重复的布局需求,repeat就可以很好的帮我们解决这种问题
当然repeat()并不是只能单独使用
.wrapper{
display: grid;
grid-template-columns: 1fr repeat(2,2fr) 1fr;
}
我们还可以将repeat跟正常的fr单位混这写,当然如果用px做单位也是可以的
repeat的第二个参数并不是只能写一个,它也是支持写多个份数的
.wrapper{
display: grid;
grid-template-columns: repeat(2,1fr 2fr);
}
效果
隐式网格和显式网格
我们在上面并没有定义grid-template-rows但是我们发现我们的网格中也出现了好几行,这些行就是网格为我们隐式创建的行
在grid-template-columns和grid-template-rows明确定义出来的列和行就是显式的网格,如果网格元素的数量多于我们显式声明的行和列划分出来的元素数量,那个网格系统就会为我们创建隐式的网格
轨道大小和minmax()
可以在grid-auto-rows属性中使用minmax()函数对行的高度进行更好的设置
在需求中如果有一个最小行高的需求,例:如果内容少,行高为44px,如果内容多,行高要跟随响应的内容变大,minmax可以写为minmax(44px, auto),auto就意味着行高将会根据内容自动调整,但是最小也是44px
HTML
<div class="wrapper">
<div>北京<p>首都</p></div>
<div>上海</div>
<div>三亚</div>
<div>香港</div>
<div>杭州</div>
<div>广州</div>
<div>成都</div>
<div>深圳</div>
<div>苏州</div>
<div>桂林</div>
<div>西安</div>
<div>厦门</div>
</div>
CSS
.wrapper{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(44px, auto);
}
效果
对应列也有grid-auto-columns属性来进行相关设置
3. 网格线
在定义网格时,我们定义而定是网格轨道,不是网格线,grid会为我们创建网格线并赋予编号,网格线如下所示
跨轨道放置网格元素
在网格线的基础上,我们可以通过网格线去跨轨道放置网格元素
我们可以在网格元素的CSS属性中使用grid-column-start和grid-column-end来设置网格元素占据的列数
通过grid-row-start和grid-row-end来设置网格元素占据的行数
HTML
<div class="wrapper">
<div class="title">热门城市</div>
<div class="capital">北京
<div>首都</div>
</div>
<div>上海</div>
<div>三亚</div>
<div>香港</div>
<div>杭州</div>
<div>广州</div>
<div>成都</div>
<div>深圳</div>
<div>苏州</div>
<div>桂林</div>
<div>西安</div>
<div>厦门</div>
</div>
CSS
.wrapper{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(44px, auto);
}
.title{
grid-column-start: 1;
grid-column-end: 4;
}
.capital{
grid-row-start: 2;
grid-row-end: 4;
}
效果
热门城市这个网格元素的列从第1根列网格线开始,到第4根列网格线结束
北京 首都的行从第2根行网格线开始,到第4根行网格线结束,其余没有设置的就按照默认的方式放到网格中
当然,大家可以根据自己的喜好,按照上述方式去随意放置网格元素
4. 网格单元
一个网格单元是网格元素中最小的单位,类似于表格中的单元格 如上方的案例图中一个格子就是一个网格单元
5. 网格区域
网格区域是个矩形,如上述图中热门城市这个网格元素,我们虽然对他进行了扩展,但是不管怎么扩展它都只能是一个矩形,不能扩展成L形或其他形状
6. 网格间距
通过网格间距以及上面提到的一些东西,我们就可以完全实现要实现的内容了
网格间距定义在网格容器的CSS中,有三个属性grid-column-gap设置列之间的间距,grid-row-gap设置行之间的间距,grid-gap同时设置行和列之间的间距
HTML代码
<div class="wrapper">
<div class="title">热门城市</div>
<div>北京</div>
<div>上海</div>
<div>三亚</div>
<div>香港</div>
<div>杭州</div>
<div>广州</div>
<div>成都</div>
<div>深圳</div>
<div>苏州</div>
<div>桂林</div>
<div>西安</div>
<div>厦门</div>
</div>
CSS代码
.wrapper{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 2px;
grid-row-gap: 2px;
/*grid-gap: 2px*/ /*这里或者这样写*/
}
其他的样式代码做了些调整,这里也再放出来吧
.wrapper{
width: 414px;
background-color: #f5f5f5;
font-size: 12px;
margin: 0 auto;
border: 1px solid #00bcd4;
}
.wrapper > div{
box-sizing: border-box;
line-height: 44px;
background-color: #fff;
text-align: center;
}
.wrapper>.title{
grid-column-start: 1;
grid-column-end: 4;
background-color: #f5f5f5;
text-align: left;
text-indent: 10px;
line-height: 36px;
}
效果
7. 嵌套网格
嵌套网格
网格单元也可以作为网格容器,里面再实现一个小的网格布局
这里我在外层新建了一个网格容器 HTML代码
<div class="outWrapper">
上述代码复制了6份
</div>
CSS代码
.outWrapper{
background-color: #00bcd4;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 10px;
grid-auto-columns: minmax(414px,auto)
}
效果
子网格
在Level 1网格规范中有个子网格的特性,即上述代码中我们将outWrapper内部的子网格的display不要设置为grid,而是设置为display:subgrid
注
规范中虽然有子网格特性,但是子网格还没有在
任何浏览器中实现,并且可能随时被移除,了解就好
8. 使用z-index控制层级
由于我们可以控制网格元素的位置,有可能就会产生覆盖现象 HTML
<div class="wrapper">
<div class="title">热门城市</div>
<div class="capital">北京
<div>首都</div>
</div>
<div>上海</div>
<div>三亚</div>
<div>香港</div>
<div>杭州</div>
<div>广州</div>
<div>成都</div>
<div>深圳</div>
<div>苏州</div>
<div>桂林</div>
<div>西安</div>
<div>厦门</div>
</div>
CSS
.wrapper{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 2px;
grid-row-gap: 2px;
}
.wrapper>.title{
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 2;
background-color: #f5f5f5;
}
.capital{
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 3;
}
效果
此时北京 首都网格元素覆盖了热门城市的部分内容
如果我们想让热门城市覆盖北京,只需要给热门城市加上z-index属性即可,值我这里设置的2,就可以覆盖了
效果