方法总结:
方法一:纯CSS布局
缺点:
每个item是从上到下排列的。如果需要动态加载item,(⊙o⊙)…那真是糟糕透顶!
这个就了解了解,实际项目中不会这样写的。
方法二:JS计算位置
利用绝对定位absolute
,通过JS计算每个item的的top
和left
值
实际项目中图片的宽高一般是由后端返回过来。这样前端就不需要计算图片宽高,用户体验会更好!
总之,具体问题具体分析,万一后端没返回宽高的勒 (︶︹︺)
方法三:使用插件
持续更新中。。。
方法1.1:multi-column多列布局瀑布流
演示代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>multi-columns瀑布流布局</title>
<style>
.container {
margin: 0 auto;
width: 1000px;
column-count: 5; /* 列数 */
column-gap: 20px; /* 列间距 */
}
.item {
margin-bottom: 10px;
/* 防止多列布局,分页媒体和多区域上下文中的意外中断 */
break-inside: avoid;
}
.item img{
width: 100%;
height:100%;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
</body>
</html>
方法1.2:Flex弹性布局瀑布流
演示代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flexbox瀑布流布局</title>
<style>
.wrapper{
display: flex;
flex-direction: row; /* 每列container 水平排列*/
justify-content: space-between; /* 两端对齐,间隔相等*/
margin: 0 auto; /* 整体居中 */
width:1000px;
}
.container{
width:240px;
}
.item{
margin-bottom:10px;
}
.item img{
width:100%;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
</div>
</body>
</html>
方法2.1:原生JS瀑布流
实际项目中需要根据具体情况做相应的改动
大致情况有:
- 瀑布流整体的宽度(下面的演示代码宽度为全屏)
- 内部
item
元素的高度(有些项目item
里不单单就是一张图片,还有文本。下面的演示代码只含一张图片) - 实际请求数据时,图片还没加载完就执行
js
,导致获取的宽高都为0;需要利用img.onload
来判断图片是否加载完毕,再执行位置的计算 - css动画效果
演示代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS实现瀑布流1</title>
<!-- 样式部分 -->
<style>
.container{
position:relative;
}
.item{
overflow: hidden;
position: absolute;
}
.item img {
width: 95%;
}
</style>
</head>
<body>
<!-- html 部分 -->
<div id="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
<!-- js 部分 -->
<script>
// 封装成一个函数
function waterFall() {
var container = document.getElementById('container');
var items = container.children;
var columns = 5; //5列
//根据屏幕宽度和设定的列数, 计算出实际item的宽度
var pageWidth = getClient().width;
var itemWidth = parseInt(pageWidth/columns);
// 存储每列当前的高度
var arr = [];
for (var i = 0; i < items.length; i++) {
// 设置每个item的宽度
items[i].style.width=itemWidth+'px';
// 根据实际图片的宽高比列 计算出实际item的高度
var height = items[i].querySelector("img").height;
var width = items[i].querySelector("img").width;
var bi = itemWidth/width; //获取缩小的比值
var itemHeight = parseInt(height*bi); //图片的高度*比值 = item的高度
// 第一行,item的top都为0,特殊处理
if (i < columns) {
items[i].style.top = 0;
items[i].style.left = itemWidth * i + 'px';
arr.push(itemHeight);
} else {
// 其他行:通过寻找arr数组里的最小高度,来计算item的位置
// 找到arr数组中最小高度和它的索引
var minHeight = arr[0];
var index = 0;
for (var j = 0; j < arr.length; j++) {
if (minHeight > arr[j]) {
minHeight = arr[j];
index = j;
}
}
// 设置该item的位置
// top值就是最小列的高度
items[i].style.top = arr[index] + 'px';
// left值就是最小列距离左边的距离
items[i].style.left = items[index].offsetLeft + 'px';
// 修改最小列的高度
// 最小列的高度 = 当前自己的高度 + 拼接过来的高度
arr[index] = arr[index] + itemHeight;
}
}
}
// 获取屏幕宽高 clientWidth 处理兼容性
function getClient() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
}
// 返回垂直方向滚动的像素 scrollTop兼容性处理
function getScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
}
window.onload = function() {
// 一进来就调用一次
waterFall();
};
// 页面尺寸改变时实时触发waterFall()函数,重新排列
window.onresize = function() {
waterFall();
};
// 当滚动到最后item的时候,模拟ajax请求获取数据,动态添加到html中
window.onscroll = function() {
var container = document.getElementById('container');
var items = container.children;
// 当屏幕高度+滚动高度 >= 最后一个item的距外层container的高度, 即滚动到最后了
if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
// 模拟 ajax 获取的数据
var datas = [
"img/bg13.jpg",
"img/bg14.jpg",
"img/bg15.jpg",
"img/bg16.jpg",
"img/bg17.jpg",
"img/bg1.jpg",
"img/bg2.jpg",
"img/bg3.jpg",
"img/bg4.jpeg",
];
// 循环获取到的数据,添加到hmtl中
for (var i = 0; i < datas.length; i++) {
var div = document.createElement("div");
div.className = "item";
div.innerHTML = '<img src="' + datas[i] + '" alt="">';
container.appendChild(div);
};
// 重新排列一下
waterFall();
}
};
</script>
</body>
</html>
方法2.1:JQ瀑布流
实际项目中需要根据具体情况做相应的改动
大致情况有:
- 瀑布流整体的宽度(下面的演示代码宽度为全屏)
- 内部
item
元素的高度(有些项目item
里不单单就是一张图片,还有文本。下面的演示代码只含一张图片) - 实际请求数据时,图片还没加载完就执行
js
,导致获取的宽高都为0;需要利用img.onload
来判断图片是否加载完毕,再执行位置的计算 - css动画效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JQ实现瀑布流布局</title>
<style>
.container{
width: 100%;
position:relative;
}
.item{
overflow: hidden;
position: absolute;
}
.item img {
width: 95%;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
<script src="js/jquery-3.4.1.min.js"></script>
<script>
function waterFall() {
// 1- 确定图片的宽度 - 滚动条宽度
var pageWidth = getClient().width-8;
var columns = 5; //3列
var itemWidth = parseInt(pageWidth/columns); //得到item的宽度
$(".item").width(itemWidth); //设置到item的宽度
var arr = [];
$(".container .item").each(function(i){
var height = $(this).find("img").height();
var width = $(this).find("img").width();
var bi = itemWidth/width; //获取缩小的比值
var boxheight = parseInt(height*bi); //图片的高度*比值 = item的高度
if (i < columns) {
// 2- 确定第一行
$(this).css({
top:0,
left:(itemWidth) * i
});
arr.push(boxheight);
} else {
// 其他行
// 3- 找到数组中最小高度 和 它的索引
var minHeight = arr[0];
var index = 0;
for (var j = 0; j < arr.length; j++) {
if (minHeight > arr[j]) {
minHeight = arr[j];
index = j;
}
}
// 4- 设置下一行的第一个盒子位置
// top值就是最小列的高度
$(this).css({
top:arr[index],
left:$(".container .item").eq(index).css("left")
});
// 5- 修改最小列的高度
// 最小列的高度 = 当前自己的高度 + 拼接过来的高度
arr[index] = arr[index] + boxheight;
}
});
}
//clientWidth 处理兼容性
function getClient() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
}
// 返回垂直方向滚动的像素 scrollTop兼容性处理
function getScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
}
// 页面尺寸改变时实时触发
window.onresize = function() {
//重新定义瀑布流
waterFall();
};
//初始化
window.onload = function(){
//实现瀑布流
waterFall();
}
// 当滚动到最后item的时候,模拟ajax请求获取数据,动态添加到html中
window.onscroll = function() {
var container = $(".container");
var items =$(".container .item");
// 当屏幕高度+滚动高度 >= 最后一个item的距外层container的高度, 即滚动到最后了
if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
// 模拟 ajax 获取的数据
var datas = [
"img/bg13.jpg",
"img/bg14.jpg",
"img/bg15.jpg",
"img/bg16.jpg",
"img/bg17.jpg",
"img/bg1.jpg",
"img/bg2.jpg",
"img/bg3.jpg",
"img/bg4.jpeg",
];
// 循环获取到的数据,添加到hmtl中
for (var i = 0; i < datas.length; i++) {
container.append(`<div class="item"><img src=${datas[i]}></div>`);
};
// 重新排列一下
waterFall();
}
};
</script>
</body>
</html>
方法3.1:使用插件:Masonry
动态加载功能,后续添加。。。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Masonry插件使用</title>
<style>
.grid{
width:1040px;
margin: 0 auto;
}
.grid-item{
width:200px;
margin-bottom: 10px;
}
.grid-item img{
width:100%;
}
</style>
</head>
<body>
<div class="grid">
<div class="grid-item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="grid-item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
<script src="js/jquery-3.4.1.min.js"></script>
<script src="js/masonry.pkgd.min.js"></script>
<script>
$('.grid').masonry({
// options
itemSelector: '.grid-item',
columnWidth: 200,
gutter:10, // 网格水平方向边距(即列与列之间的距离)
});
</script>
</body>
</html>