前言
在日常开发中经常会遇到 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
支持良好。