需求
要实现一个多行多列的布局,每行 4 列,行数不固定,如下图所示:
怎么实现
方案一:flexbox
一般来说,涉及到多列,首先想到的是 flexbox. 尤其是常见的两行多列布局,flex 屡试不爽。
假设 HTML 是这样的:一个容器元素(class 为 box)里有十个子元素(class 为 box-item)。
这个四行多列,先用 flex 实现看看。
CSS 代码如下:
.box {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.box .box-item {
width: 100px;
margin-bottom: 10px;
}
效果如下图:
从上图可见,justify-content: space-between; 优雅地令元素平分整行的宽度。
可是如最后一行所示,当元素无法占满一行之时,布局却不尽人意,我们希望最后一行的元素是左对齐的。
修复一下看看。
改造后的 flexbox
.box {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.box .box-item {
width: 100px;
margin-bottom: 10px;
margin-right: 10px;
}
.box .box-item:nth-of-type(4n) {
margin-right: 0;
}
这里用 justify-content: flex-start; 来实现元素的左对齐。然后在子元素上加 margin-right: 10px; 来保证同一行的元素之间有空隙。
效果如下:
可以看到,最后一行的元素也是左对齐的。
注意到,上面有这样的代码:
.box .box-item:nth-of-type(4n) {
margin-right: 0;
}
.box-item:nth-of-type(4n) 选中了第 4n 个子元素,即第 4 个,第 8 个。因为这些元素都是行尾的元素,需要令它们的 margin-right 为 0, 不然行宽会大于容器宽度,导致元素被挤到下一行,如图:
怪不得 flexbox 中文名叫做弹性布局,果然很弹。
这里的 flexbox 实现了四列多行的布局。线上 Demo 点这里。
可以看到代码不仅要设置容器的样式,还要设置子元素的样式,一大堆。
有没有更为简洁优雅的解决方案呢?请看接下来的 grid 布局。
方案二:grid 布局
grid 布局,中文名是网格布局。顾名思义,它可以让元素像网格一样呈现,网格自身就是多行多列的。
接下来用 grid 实现四行多列的布局:
.box {
display: grid;
grid-template-columns: repeat(4, 100px);
grid-column-gap: 10px;
grid-row-gap: 10px;
}
实现如图所示:
可以看到,利用 grid 布局,只设置容器的样式,就能够实现多行多列布局。线上 Demo 点这里。
代码中, grid-template-columns: repeat(4, 100px); 定义了 grid 布局中列的规则。其中 repeat 是一个函数,它接收两个参数,第一个是重复的次数,第二个是重复的值。 grid-template-columns: repeat(4, 100px); 相当于 grid-template-columns: 100px 100px 100px 100px;.
grid-column-gap: 10px; 和 grid-row-gap: 10px; 分别定义了 grid 布局中列之间的间隔以及行之间的间隔。
兼容性
Grid
若使用一些相对较新的 CSS 特性,不得不考虑的一个点就是兼容性,下面来看看 grid 布局的兼容性。
下图是 caniuse 网站的查询结果:
图上绿色的部分代表浏览器支持,一片绿,表示还是有不少浏览器支持的。Chrome 和 Firefox 根本不用担心。
Flexbox
Flexbox 兼容性:
由图可知,flexbox 的兼容性明显好于 grid 布局。
总结
本文介绍了两种实现多行多列布局的方案,分别是 flexbox 和 grid.
从代码层面来说,grid 的实现要比 flexbox 更加简洁。
从兼容性来说,更多的浏览器支持 flexbox.
参考
[1] 阮一峰.CSS Grid 网格布局教程
[2] MDN.grid-template-columns