效果图如下:
设计思路:
- 封装一个函数,可以接受五个参数分别为容器id(或class)名称、容器中内容项id(或class)名称、容器中内容展示列数、容器中列间隔距离、容器中行间隔距离。当我们下次再有地方需要生成瀑布流的时候,我们就可以直接传入对应的参数就可以了。
- 获取每一列的宽度以及图片的集合
- 生成一个数组(数组的长度是瀑布流列的长度),用于存放每一列已经放置了图片的总高度,方便后面比较大小,知道哪一列的图片最少,将图片加入到哪一列
- 先挨个将图片放入到第一行
- 然后比较哪一列的高度值最小,然后将带有定位的图片定位至哪一些列,然后将该列的高度进行增加一个图片的高度。
- 在放置下一张图片的时候,重复第五步即可
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab-container {
position: relative;
}
.tab-container .tab-item {
position: absolute;
height: auto;
border: 1px solid #000;
background: white;
break-inside: avoid;
text-align: center;
}
.tab-container .tab-item img {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<div class="tab-container" id="tabContainer">
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/business-people_PAQJGIXNYI.jpg" />
</div>
<div class="tab-item">
<img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/coastal-landscape_80QIX6YO2W.jpg" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/girl-field_RY7NGH96SF.jpg" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/mushrooms-forest_LUYHIZXNWX.jpg" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
</div>
<div class="tab-item">
<img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
</div>
<div class="tab-item">
<img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
</div>
<div class="tab-item">
<img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
</div>
<div class="tab-item">
<img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
</div>
<div class="tab-item">
<img src="https://cdn.stocksnap.io/img-thumbs/280h/dog-sunglasses_ZVCXJVXL75.jpg" />
</div>
</div>
<script>
window.onload = function () {
waterFall('#tabContainer', '.tab-item'); //实现瀑布流
}
/**
* @param { string } wrapIdName 容器id(或class)名称
* @param { string } contentIdName 容器中内容项id(或class)名称
* @param { number } column 容器中内容展示列数 默认为4
* @param { number } columnGap 容器中列间隔距离 默认为20
* @param { number } rowGap 容器中行间隔距离 默认为20
*/
function waterFall(wrapIdName, contentIdName, columns = 4, columnGap = 20, rowGap = 20) {
// 获得内容可用宽度(去除滚动条宽度)
const wrapContentWidth = document.querySelector(wrapIdName).offsetWidth - 8;
// 间隔空白区域
const whiteArea = (columns - 1) * columnGap;
// 得到每列宽度(也即每项内容宽度)
const contentWidth = parseInt((wrapContentWidth - whiteArea) / columns);
// 得到内容项集合
const contentList = document.querySelectorAll(contentIdName);
// 成行内容项高度集合
const lineConentHeightList = []
for (let i = 0; i < contentList.length; i++) {
// 动态设置内容项宽度
// 设置完宽度之后高度也会等比例的缩小
contentList[i].style.width = contentWidth + 'px';
// 获取内容项高度
const height = contentList[i].clientHeight;
if (i < columns) {
// 第一行按序布局
contentList[i].style.top = 0;
contentList[i].style.left = contentWidth * i + columnGap * i + 'px';
// 将行高push到数组
lineConentHeightList.push(height)
console.log(lineConentHeightList);
} else {
// 其他行
// 获取数组最小的高度 和 对应索引
let minHeight = Math.min(...lineConentHeightList)
let index = lineConentHeightList.findIndex(listH => listH === minHeight)
contentList[i].style.top = (minHeight + rowGap) + 'px';
contentList[i].style.left = (contentWidth + columnGap) * index + 'px';
// 修改最小列的高度 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 行间距
lineConentHeightList[index] += height + rowGap
}
}
}
</script>
</body>
</html>