grid 实现完美的水平铺满、间隔一致的自适应布局

需求描述

  • 在一个容器元素下,有不确定数量的子元素,要求他们水平铺满,并且在当前行的最左边和最右边的子元素距离父元素左边缘和右边缘都是无缝贴合的。
  • 每个子元素之间的间隔必须一致。
  • 当浏览器窗口大小变动自适应。

尝试方案

惯性思维,一眼看过去就是 flex弹性盒子 一把梭,于是我有了以下这种方案:

index.html 文件

html 复制代码
<body>
  <div class="father">
    <div class="child">Child1</div>
    <div class="child">Child2</div>
    <div class="child">Child3</div>
    <div class="child">Child4</div>
    <div class="child">Child5</div>
    <div class="child">Child6</div>
    <div class="child">Child7</div>
    <div class="child">Child8</div>
    <div class="child">Child9</div>
    <div class="child">Child10</div>
  </div>
</body>

index.scss 文件

css 复制代码
.father {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: flex-start;
  width: 100%;
  padding: 10px 0 10px 20px;

  .child {
    margin-right: 14px;
    margin-bottom: 14px;
    // 其他卡片样式
  }
}

可以看到,我会为每个子元素都设置 margin-top 以及 margin-right 来固定他们之间的间距,但是因为每一行最右边的子元素也有 margin-right ,为了补偿这个,我就将父元素的 padding-right 去掉了,这样做的坏处太多了,需要自己去计算,做补偿,而且右边有时候容纳不下一个完整的子元素,就会导致换行而留下一大片白。。

改进方案

Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大

首先我们需要给容器指定为 grid 网格布局,就像 flex 一样:

css 复制代码
.father {
  display: grid;
}

接着要为其划分列数, grid-template-columns 属性可定义每一列的列宽,假如代码如下,我们将容器划分成 3 列,每列宽度为容器的 100px

css 复制代码
.father {
  grid-template-columns: 100px 100px 100px;
}

但是这个时候我们看到的效果会是下面这样:

子元素并没有把父元素占满,这显然不是我们想要的效果,幸亏有 repeat() 函数帮助我们简化重复值, 它接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值 。上面的代码完全可用以下代码代替:

css 复制代码
.father {
  grid-template-columns: repeat(3, 100px);
}

当然,这只是第一步,我们还需要借助 auto-fill 关键字,在我们需要容器能尽可能容纳子元素时,就需要用到它,表示自动填充,我的理解是 repeat() 接受了这个 auto-fill 的参数时,会去自动计算容纳的数量,就好像你事先算出来这个容器能容纳多少子元素,然后把这个"多少"传给该函数一样。这时候代码如下:

css 复制代码
.father {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
}

现在图形如下,已经越来越接近我们的目标了:

但是很显然,右边有一个空隙, justify-content 属性拯救我们,它整个内容区域在容器里面的水平位置,当我设置其为 space-between 时,意味着子元素之间的间隔相等,而子元素与容器边框之间没有间隔

不过子元素之间还是没有间隔,简单设置一下属性 gap 即可,它是 column-gaprow-gap 的合并简写,分别表示列与列行与行之间的间距,现在代码如下:

css 复制代码
.father {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  justify-content: space-between;
  gap: 14px 4px;
}

由此简单的几行代码就已经完美实现了我们想要的效果:

当然,注意一下 grid 网格布局的兼容性

相关推荐
修己xj4 小时前
打造专属博文封面神器:一个开源免费的博文封面生成器ThisCover
前端
kyriewen4 小时前
面试8家前端岗位后,我发现了一个残酷的事实:AI不是加分项,是门槛
前端·javascript·面试
Fighting_p4 小时前
【面试 - el-select问题及解决】wujie 微前端下子系统 el-select 多选 filterable 过滤失效
前端
吃口巧乐兹4 小时前
AI 全栈时代,为什么要服务端使用 NestJs
前端
yingyima4 小时前
Redis 延迟任务队列:凌晨3点服务器报警的救星
前端
weiggle4 小时前
第三篇:可组合函数(Composable)——Compose 的基石
android·前端
前端环境观察室4 小时前
别只看 task success:AI Agent 浏览器自动化真正要补的是环境证据链
前端·后端
huakoh4 小时前
LangChain 实战:用混合检索啃下 1000 页 PDF,搭一个长文档问答 Agent
前端
Dazer0075 小时前
Edge 浏览器绕过 HTTPS 证书错误
前端·https·edge
元让_vincent5 小时前
Spark 2.0:面向 Web 的 3DGS 可视化与大场景渲染平台详解
前端·3d·spark·渲染·轻量化·3dgs·lod