认识网格布局(Grid Layout)
相信学web前端的朋友们应该对“布局”这个概念不陌生吧,在前端布局里有这么几大布局技术:
- 流式布局(Flow Layout 默认)
- 浮动布局(Float Layout)
- 定位布局(Position Layout)
- 表格布局(Table Layout 已弃用)
- 框架布局(Frame Layout 不太常用)
CSS3之后新增了两个新布局
- 弹性布局(Flexbox Layout)
- 网格布局(Grid Layout)
之前用flex布局用着挺爽的,响应效果很强。然而为什么想起去接触网格布局这个东西呢?emmmm最近在做一个小程序,要实现的效果是这样的:
发现箭头指着这一块的布局好复杂啊,首先它大体上一行有五列,然后每一列又各自有它的小布局,特别是第二列,我。。。
(以下省略对UI设计师的10000字吐槽)
于是我就想到了,好像有网格布局这么一个东西,用它应该挺合适的。虽说用浮动或者flex布局也能实现,但既然想到了就用呗,顺便长点见识。
好了,正片开始~
说起这个布局,或许大伙都想到了Bootstrap的栅格系统,没错!它俩挺像,我也这样觉得。
咱们接下来的讲解就用以下的HTML作为例子吧 ↓
<body>
<div class="grid-box">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
<div class="item item11">11</div>
<div class="item item12">12</div>
</div>
</body>
要实现网格布局,首先要给布局的父盒子声明布局为网格布局(就像弹性布局一样要先用display: flex;声明一下),网格布局跟弹性布局的实现方式有点像,它也分为 容器 和 子项目 。
display: grid; //让容器变为网格布局容器,当然你也可以赋值inline-grid,让容器同时带有内联元素的特性。
另外需要注意
注:当元素设置了网格布局,它的全部子项目所具有的column、float、clear、vertical-align属性均会失效。
接下来给容器划分网格,需要用到以下两个属性。
- grid-template-rows
- grid-template-columns
见名知意,它定义网格布局应该有几行几列,比如
.grid-box {
display: grid;
grid-template-rows: 150px 150px 150px 150px; /* 它的值有四项,代表现在的网格有四行 */
grid-template-columns: 300px 1fr 300px; /* 它的值有三项,代表现在的网格有三列 */
}
我们来看看效果,在这之前先给它赋予显示样式
.item{
border: 1px solid #000;
font-size: 50px;
}
.item:nth-child(odd) {
background-color: aqua;
color: #fff;
}
.item:nth-child(even) {
background-color: hotpink;
color: #000;
}
然后效果就很明显了,如下
以上提到的这两个属性的值,它的表示方法可以有以下几种
- 具体的像素值
- 百分值
- 带等分单位fr的值
- 使用函数repeat()表示的值
等分单位fr
CSS3专门为网格布局设计了一个新的单位,它就是fr,来自英文单词fraction(均分、等分)。怎么理解呢?直接上demo!
grid-template-columns: 1fr 1fr 1fr 1fr;
/* 它等价于 */
grid-template-columns: 25% 25% 25% 25%;
grid-template-columns: 1fr 2fr 1fr;
/* 它等价于 */
grid-template-columns: 25% 50% 25%;
哈,简单明了!现在你应该明白这个单位了叭
带函数repeat()表示的值
有时候你需要给网格定义相同宽的列或者相同高的行,两三行(列)还好说,要是十几行呢?想象一下。。。↓
/* 给网格定义12列等宽的列 */
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
天哪!这太可怕了吧。。。
其实,你可以这样做
grid-template-columns: repeat(12, 1fr);
它等价于本节的第一句css代码。
它还可以重复循环某一个规则,比如
grid-template-columns: repeat(2, 1fr 2fr);
/* 等价于 */
grid-template-columns: 1fr 2fr 1fr 2fr;
看!repeat很方便有木有
grid-gap单元格间距
再回到刚才的效果图,此时网格的各个单元格之间没有间距,你可以通过插入间距实现如下效果
此时就需要用到另一个属性grid-gap,它属于网格容器的属性。也就是说,这个属性应写在网格容器中而不是子项目中
.grid-box {
display: grid;
grid-template-rows: 150px 150px 150px 150px;
grid-template-columns: 300px 1fr 300px;
grid-gap: 10px; /* 给单元格插入10px的间距 */
}
其实,我觉得吧,这个属性好像跟单纯给子项目加margin没有啥区别,至少我目前是这样认为的。
语法
grid-gap: 行间距 列间距; (如果只写一个值,则默认行列间距共用一个值),如
grid-gap: 10px 20px;
它还可以分开写,形式如下
grid-row-gap: 10px;
grid-column-gap: 20px;
根据w3c标准,grid-gap、grid-row-gap、grid-column-gap这三个属性还可以省略grid-前缀,即写成gap、row-gap以及column-gap。
单元格的位置定位
在讲这一部分之前,我们先来认识几个概念,网格线和网格轨道
网格线
引用阮一峰阮大神的一张图 ↓
每根网格线都有它一个唯一的序号
网格轨道
即任意两条平行网格线之间夹着的区域。
好了,相信大家对于这两个概念应该明白了吧。(真是一图胜千言啊hhhhhh)
那么接下来就要介绍关于网格线定位的属性了,主要有以下四个
- grid-row-start(定位单元格的上网格线)
- grid-row-end(定位单元格的下网格线)
- grid-column-start(定位单元格的左网格线)
- grid-column-end(定位单元格的右网格线)
要理解它们也很容易,直接上demo(实现将9移到2的位置)
代码如下
.item:nth-child(9) {
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 2;
grid-column-end: 3;
}
/* 注意这些网格线定位属性都是写在子项目里的,不能写在网格容器上 */
如果你觉得看到这里还是懵逼的话,那么看下图的原理解释。
单元格合并
有时候我们布局时并不需要这样规规整整,有时需要合并某些单元格。那么可以这样做,让grid-row-end和grid-column-end往后再挪一挪就好了。
/* 让9号单元格往右扩展一个单元格单位 */
.item:nth-child(9) {
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 2;
grid-column-end: 4; /* 仔细对比此处 */
}
/* 让9号单元格往下扩展一个单元格单位 */
.item:nth-child(9) {
grid-row-start: 1;
grid-row-end: 3; /* 仔细对比此处 */
grid-column-start: 2;
grid-column-end: 3;
}
其实,合并单元格还有另外一种写法
grid-row-end: span 跨度;
grid-column-end: span 跨度;
/* 另外,当跨度是1时,grid-*-end可以省略 */
如上一个例子咱们可以这样写
.item:nth-child(9) {
grid-row-start: 1;
grid-row-end: span 2;
grid-column-start: 2;
/* grid-column-end可省略 */
}
最后
讲到这里,不知各位对于grid布局跟flex布局有啥区别吗? 我反正想到了一点,flex是一维布局(整个布局是有一条条主轴堆叠而成),而grid是二维布局(在一定程度上方便了整体的布局),在实际应用中建议flex布局和grid布局交错搭配,这样能达到很完美的自适应和响应式效果。
由于整个grid布局的知识体系太大了,所以本期就打算先这样了,临时决定分两期哈哈哈哈。相信我!下一期一定给大伙讲完,拜拜~