瀑布流布局的核心特点是元素按列排列,每一列的高度不同,新元素会优先放到高度最小的列中,整体呈现错落有致的视觉效果。使用CSS Grid实现这种布局不需要额外的JavaScript计算,仅通过CSS属性配置就能完成。

CSS Grid实现瀑布流的核心思路
要实现瀑布流效果,首先需要定义多列的网格容器,然后让网格项根据内容自动调整高度,同时利用grid-auto-flow属性控制元素的排列方向,配合grid-row-end的span属性让不同高度的元素占据不同的行数,最终形成错落的布局。
关键CSS属性说明
- grid-template-columns:定义网格的列数和每列的宽度,比如
repeat(4, 1fr)表示创建4列等宽的网格。 - grid-auto-rows:定义网格自动创建的行的最小高度,这里设置的是一个基准值,元素高度会在此基础上根据内容扩展。
- grid-auto-flow:控制自动布局的元素排列方向,设置为
dense可以让元素尽量填满网格中的空白区域,让布局更紧凑。 - grid-row-end:设置网格项跨越的行数,通过
span加上数值,让不同高度的元素占据不同的行数,实现错落效果。
完整实现代码示例
下面是一个4列瀑布流布局的完整实现,网格项的高度通过不同的内容模拟,实际开发中可以根据内容高度动态调整span的数值。
/* 网格容器样式 */
.waterfall-container {
display: grid;
/* 定义4列,每列等宽 */
grid-template-columns: repeat(4, 1fr);
/* 自动创建的行最小高度为50px */
grid-auto-rows: 50px;
/* 元素按密集排列,尽量填满空白 */
grid-auto-flow: dense;
gap: 16px;
padding: 16px;
}
/* 网格项基础样式 */
.waterfall-item {
border-radius: 8px;
background-color: #f0f0f0;
padding: 12px;
/* 默认占据1行,后续通过不同类调整跨度 */
grid-row-end: span 1;
}
/* 不同高度的网格项,模拟内容高度差异 */
.item-height-1 {
grid-row-end: span 2;
}
.item-height-2 {
grid-row-end: span 3;
}
.item-height-3 {
grid-row-end: span 4;
}
对应的HTML结构如下,通过给不同的网格项添加不同的高度类,模拟内容高度不同的情况:
<div class="waterfall-container">
<div class="waterfall-item item-height-2">内容1</div>
<div class="waterfall-item item-height-1">内容2</div>
<div class="waterfall-item item-height-3">内容3</div>
<div class="waterfall-item item-height-2">内容4</div>
<div class="waterfall-item item-height-1">内容5</div>
<div class="waterfall-item item-height-3">内容6</div>
<div class="waterfall-item item-height-2">内容7</div>
<div class="waterfall-item item-height-1">内容8</div>
</div>
动态适配内容高度的实现方式
上面的示例是固定了不同元素的高度跨度,实际开发中元素内容高度是动态的,这时候可以通过JavaScript获取每个元素的内容高度,再动态计算需要跨越的行数,然后设置对应的grid-row-end属性。
示例JavaScript代码如下:
// 获取所有网格项
const items = document.querySelectorAll('.waterfall-item');
// 基准行高,和grid-auto-rows的值一致
const baseRowHeight = 50;
// 行间隙,和gap的值一致
const rowGap = 16;
items.forEach(item => {
// 获取元素的内容高度
const itemHeight = item.offsetHeight;
// 计算需要跨越的行数,向上取整
const rowSpan = Math.ceil((itemHeight + rowGap) / (baseRowHeight + rowGap));
// 设置网格项的行跨度
item.style.gridRowEnd = `span ${rowSpan}`;
});
注意事项和适用场景
这种实现方式有以下特点:
- 纯CSS部分实现的瀑布流是近似效果,因为span的数值是预设的,动态计算的方式才能更精准适配内容高度。
- 相比JavaScript计算位置的方案,CSS Grid实现的布局性能更好,重排时开销更小。
- 适合列数固定、元素宽度一致的场景,如果元素宽度需要响应式变化,可以配合媒体查询调整
grid-template-columns的值。 - 如果网格项有动态加载的需求,需要在新元素插入到DOM后重新执行高度计算的逻辑,保证新元素也能正确适配跨度。
需要注意的是,这种方案下网格项的位置是按顺序排列后根据高度调整跨度,和传统的优先放最短列的瀑布流逻辑略有差异,如果对元素排列顺序有严格要求,还需要额外调整排序逻辑。