瀑布流布局是前端开发中常见的布局形式,尤其适合图片、卡片类内容的展示,能让不同高度的元素错落排列,充分利用页面空间。下面我们一步步讲解如何用原生JavaScript实现这种布局。

核心实现思路
实现瀑布流布局的核心逻辑分为三步:首先确定容器的列数和每列的基础宽度,然后计算每一列当前的高度,最后将每个待排列的元素放到当前高度最小的列上,更新该列的高度。
必要的前置准备
首先需要准备基础HTML结构,容器用来承载所有瀑布流元素,内部的每个子元素就是需要排列的卡片:
<div class="waterfall-container"> <div class="waterfall-item">卡片1</div> <div class="waterfall-item">卡片2</div> <div class="waterfall-item">卡片3</div> <div class="waterfall-item">卡片4</div> <div class="waterfall-item">卡片5</div> </div>
再添加基础的CSS样式,让容器为相对定位,子元素初始为绝对定位,后续通过JS计算位置赋值:
.waterfall-container {
position: relative;
width: 100%;
}
.waterfall-item {
position: absolute;
width: 200px; /* 单个卡片宽度 */
background: #f0f0f0;
margin-bottom: 10px;
box-sizing: border-box;
padding: 10px;
}JavaScript实现步骤
1. 初始化布局参数
首先需要获取容器元素,计算容器宽度,结合单个卡片宽度和间隙,得出可以排列的列数:
function initWaterfall() {
// 获取容器
const container = document.querySelector('.waterfall-container');
// 获取所有待排列的卡片
const items = document.querySelectorAll('.waterfall-item');
// 单个卡片宽度
const itemWidth = 200;
// 卡片之间的水平间隙
const gap = 10;
// 容器总宽度
const containerWidth = container.offsetWidth;
// 计算列数:容器宽度除以(卡片宽度+水平间隙),取整数部分
const columnCount = Math.floor(containerWidth / (itemWidth + gap));
// 存储每一列的当前高度,初始都为0
const columnHeights = new Array(columnCount).fill(0);
// 计算容器的左内边距,让整体居中
const containerPaddingLeft = (containerWidth - columnCount * itemWidth - (columnCount - 1) * gap) / 2;
container.style.paddingLeft = containerPaddingLeft + 'px';
}2. 计算每个卡片的位置
遍历所有卡片元素,找到当前高度最小的列,把卡片放到该列的位置,然后更新该列的高度:
function initWaterfall() {
const container = document.querySelector('.waterfall-container');
const items = document.querySelectorAll('.waterfall-item');
const itemWidth = 200;
const gap = 10;
const containerWidth = container.offsetWidth;
const columnCount = Math.floor(containerWidth / (itemWidth + gap));
const columnHeights = new Array(columnCount).fill(0);
const containerPaddingLeft = (containerWidth - columnCount * itemWidth - (columnCount - 1) * gap) / 2;
container.style.paddingLeft = containerPaddingLeft + 'px';
// 遍历每个卡片元素
items.forEach((item) => {
// 找到当前高度最小的列的索引
const minHeight = Math.min(...columnHeights);
const minIndex = columnHeights.indexOf(minHeight);
// 计算卡片的左偏移:列索引 * (卡片宽度+水平间隙)
const left = minIndex * (itemWidth + gap);
// 计算卡片的上偏移:当前列的高度
const top = minHeight;
// 设置卡片的位置
item.style.left = left + 'px';
item.style.top = top + 'px';
// 更新该列的高度:原来高度 + 卡片自身高度 + 垂直间隙
columnHeights[minIndex] = top + item.offsetHeight + gap;
});
// 设置容器高度,避免后面的元素重叠
const containerHeight = Math.max(...columnHeights);
container.style.height = containerHeight + 'px';
}3. 调用初始化函数
页面加载完成后调用初始化函数,同时监听窗口 resize 事件,在窗口大小变化时重新计算布局:
// 页面加载完成后初始化
window.addEventListener('load', initWaterfall);
// 窗口大小变化时重新计算布局
window.addEventListener('resize', initWaterfall);注意事项
- 如果卡片内容是动态加载的,比如滚动加载更多内容,需要在新卡片添加到容器后再次调用
initWaterfall函数,重新计算所有卡片的位置。 - 如果卡片中包含图片,需要确保图片加载完成后再计算高度,否则获取的
offsetHeight可能不准确,可以在图片的onload事件中触发布局计算。 - 可以根据实际需求调整卡片的宽度、间隙等参数,只需要修改对应的变量值即可适配不同的布局需求。
JavaScript瀑布流布局DOM操作offsetHeight修改时间:2026-06-07 03:11:18