css 实现等宽div均匀分布,超出换行保持均匀分布

前言

在日常开发中经常会遇到 list 列表,一行展示固定等宽的元素、均匀分布、超出自动换行也保持均匀分布的效果。这篇文章记录一下使用不同方式来实现这个效果。

页面dom结构

html 复制代码
<div class="list">
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <div class="item">元素</div>
    <!-- ...多个itme -->
</div>

实习方式 1(float)

发现问题

  • 一行显示 4个元素(可自定义),宽度变化时保持 "平均分布",超出部分自动换行保持 "居左" ,
css 复制代码
.list{
   width: 100%;
}
.item{
    float: left;
    width: 24.73%;
    height: 100px;
    margin-right: 10px;
    background-color: #abd3ad;
}
.item:nth-child(4n) {
    margin-right: 0;
}

使用 float + 宽度百分比实现, 一行 4 个, 100 / 4 = 25, 但是 25% 肯定不行,因为每个 item 是有 margin-right: 10px 的。 所以 item 宽度为 24% 时效果如下,右侧有空白:

那一点点加大发现当 width为 24.73%时

  • 浏览器窗口铺满效果

可以看到,当前浏览器窗口完全铺满当前笔记本屏幕的效果是 ok 的,左右边距、基本上符合预期效果。

  • 浏览器窗口宽度缩小

当把浏览器窗口宽度调小后,发现一行展示不下 4个盒子了,导致了换行,且其中部分 item 的边距重叠了,整体样式乱掉。

解决

所以,item 的宽度不能这样直接写死, 应该计算一下: width = 100% - (分布个数4-1) * 间隙值

这里的 4-1 是因为一行要排列 4 个,减 1 是因为最后一个元素是不需要 margin-right: 10px

所以计算为: 100% - 3 * 5px = 100% - 15px, 然后一行是4 个元素 最后除以 4,就是每个 item 的具体宽度,得到的样式为: width: calc((100% - 15px) / 4)

然后查看效果,浏览器窗口宽度撑满屏幕和变小都是保持一行 4 个元素,均匀分布。只不过当窗口宽度变小后 item 的宽度也会被压缩,因为我们的宽度单位是百分比,但 item 布局不会乱掉。

实现方式 2 (flex)

  • 一行显示 3个元素(可自定义),宽度变化时保持 "平均分布",超出部分自动换行保持 "居左"
css 复制代码
<style>
.list {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    /* 替代space-between布局方式 */
    justify-content: flex-start;
}
.item {
    margin: 0 5px 5px 0;
    /* 这里的10px 同上计算方式,可以根据实际的分布个数和间隙区调整 */
    flex: 1;
    width: calc((100% - 10px) / 3);
    height: 120px;
    /* 加入这两个后每个item的宽度生效 */
    min-width: calc((100% - 10px) / 3);
    max-width: calc((100% - 10px) / 3);
    background-color: #cacaca;
}
/* 去除item 第3n个的 margin-right */
.item:nth-child(3n) {
    margin-right: 0;
}
</style>
  • 上述代码关于 flex:1 ,可以简化为:
css 复制代码
<style>
.item {
    margin: 0 5px 5px 0;
    flex: 0 0 calc((100% - 10px) / 3);
    height: 120px;
    background-color: #cacaca;
}
/* 去除item 第3n个的 margin-right */
.item:nth-child(3n) {
    margin-right: 0;
}
</style>
  • 效果

实现方式 3(flex)

css 复制代码
.list {
    display: flex;
    flex-wrap: wrap;
    margin: -5px; /* 调整容器外边距以抵消内部间距 */
}
.item {
    flex: 0 0 calc(33.333% - 10px);
    margin: 5px; /* 统一边距 */
    height: 120px;
    background-color: #cacaca;
}

优点:

  • 统一边距:所有项目都使用相同的边距,避免了特殊处理。
  • 简单明了:减少了对特定子元素样式的需求。

实现方式 4(CSS Grid)

css 复制代码
.list {
    display: grid;
    grid-template-columns: repeat(3, 1 fr);
    gap: 10px; /* 使用 gap 属性设置行列间距 */
}

.item {
    height: 120px;
    background-color: #cacaca;
}

使用 Grid 方式的优点:

  • 简洁:不需要为每个项目指定宽度或处理边缘情况。
  • 响应式:可以通过媒体查询轻松调整列数。
  • 自动处理间距gap 属性会自动处理所有间距问题。

实现方式 5(Tailwind CSS)

html 复制代码
<div class="grid grid-cols-3 gap-4">
   <div class="h-96 bg-gray-300"></div>
   <div class="h-96 bg-gray-300"></div>
   <div class="h-96 bg-gray-300"></div>
   <!-- 更多 .item 元素 -->
</div>

这种方法的优点是:

  • 快速开发:无需编写额外的 CSS,直接在 HTML 中应用类名即可。
  • 一致性和维护性:遵循一致的设计系统,易于维护和扩展。

总结

至此, 使用几种不同方法实现了多元素等宽的列布局。 比较推荐的是使用 CSS Grid ,因为它不仅代码简洁,而且提供了更好的控制力和灵活性。此外,它还更容易进行响应式设计和其他复杂的布局调整。前提是目标浏览器对 CSS Grid 支持良好。

相关推荐
程序猿小D3 分钟前
【完整源码+数据集+部署教程】【零售和消费品&存货】价格标签检测系统源码&数据集全套:改进yolo11-RFAConv
前端·yolo·计算机视觉·目标跟踪·数据集·yolo11·价格标签检测系统源码
吴鹰飞侠11 分钟前
AJAX的学习
前端·学习·ajax
JNU freshman17 分钟前
vue 技巧与易错
前端·javascript·vue.js
落一落,掉一掉25 分钟前
第十二周 waf绕过和前端加密绕过
前端
Asort25 分钟前
JavaScript设计模式(十六)——迭代器模式:优雅遍历数据的艺术
前端·javascript·设计模式
Coffeeee34 分钟前
Labubu很难买?那是因为还没有用Compose来画一个
前端·kotlin·android jetpack
我是日安34 分钟前
从零到一打造 Vue3 响应式系统 Day 28 - shallowRef、shallowReactive
前端·javascript·vue.js
开源之眼36 分钟前
深入理解 JavaScript 报错:TypeError: undefined is not a function
前端·javascript
LRH36 分钟前
时间切片 + 双工作循环 + 优先级模型:React 的并发任务管理策略
前端·react.js
用户34216749055239 分钟前
Java高手速成--吃透源码+手写组件+定制开发教程
前端·深度学习