前端多种方式实现网格布局

2,728 阅读4分钟

前端开发经常会遇到网格的布局,网格的实现方式有很多种,今天就通过一个 Demo 来展示一下多种网格实现方式

容器和网格内项目配置

设定容器的宽固定为 290,项目之间左右上下间隔 10px,每行展示 5 个项目,item 的样式表如下

.item {
  width: 50px;
  height: 50px;
  background-color: #fca0a3;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
}

flex 布局

flex 可以通过设置 flex-warp: wrap 实现换行

justify-content: space-between

容器内撑满容器主轴的长度,项目之间的间隔相等,这样自然而然的想起了 space-between,只需要在容器设置一下即可,项目的上下间隔需要手动设置一下:

.flex-container-1 {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.item {
  width: 50px;
  height: 50px;
  background-color: #fca0a3;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
  /* 设置上下间隔  */
  margin-bottom: 10px;
}
<div class="flex-container-1">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="item">10</div>
  <div class="item">11</div>
  <div class="item">12</div>
</div>

这样看起来没什么问题,但是运行结果是不对的,运行的结果如下:

造成这个效果的原因也是和 space-between 有关,space-between 有个规则就是会占满容器主轴的长度,这个例子的主轴是 X 轴,也就是宽度,先占满宽度,然后容器内项目的间隔相等,就变成了这个样子,这样也可以知道当最后一行只要不是 1 个项目或者满项目的时候,页面的最后一行都是异常的

justify-content: flex-start

既然需要最后一行按正常排序排序,只能用 flex-start 了,这样的话,项目的左右边距要先设定好,但是单单设定 margin-right: 10px 是不行的,因为容器主轴长只有 290px,超长了,另外,如果修改容器主轴长,让一行能放的下,最后一个依旧是异常的,所以需要处理行最后一个项目,需要用到 nth-of-type() 这个伪类

.flex-container-2 {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}
.item {
  width: 50px;
  height: 50px;
  background-color: #fca0a3;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
  margin-bottom: 10px;
  /* 设置左右间隔 */
  margin-right: 10px;
}
/* 处理每行最后一个元素 */
.item:nth-of-type(5n) {
  margin-right: 0;
}

这样修改之后就可以看到想要的效果了,如下图

flex 布局实现网格布局的方式大概就这样,flex 的好处是兼容性比较好,比较常见,在 flutter 里面也是比较重要的布局方式

Grid 布局

网格布局不应该优先想到 Gird 布局么,还是这个布局方式在移动端支持不太好,所以生产环境都不太敢用,可以看看 caniuse 的兼容性报告,can I use grid
Grid 本来就用来实现网格布局的, 所以实现这个效果很简单,设置成 5 列,然后设置行和列之间的间隔,不需要在项目之间设置 margin 或者 padding

.grid-container {
  display: grid;
  /* 以下五种方式都可以实现 */
  grid-template-columns: repeat(5, 1fr);
  /* grid-template-columns: repeat(5, 50px); */
  /* grid-template-columns: 50px 50px 50px 50px 50px; */
  /* grid-template-columns: 1fr 1fr 1fr 1fr 1fr; */
  /* grid-template-columns: repeat(auto-fill, 50px); */
  /* 设置上下和左右的间距 */
  row-gap: 10px;
  column-gap: 10px;
}

这种布局对于 Grid 布局来说简直小菜一碟, Grid 布局能实现的效果很多,可以参考一下阮一峰的 博客Grid 布局日常使用起来很方便,但是如果页面需要兼容比较老的移动端设备的话,建议最好别用,兼容性问题很大。

传统布局

传统布局实现方式也很简单,可以参考一下,就这个布局的实现方式,用三个行,间隔的实现可以设置右边的 margin ,然后对行最后一个进行处理,也可以参考 ant-design 栅格的实现方式,条条大路通罗马