挪动端瀑布流布局是一种比拟风行的网页布局形式,视觉上来看就是一种像瀑布一样垂直落下的排版。每张图片并不是显示的正正方方的,而是有的长有的短,呈现出一种不规则的形态。然而它们的宽度通常都是雷同的
因为挪动端瀑布流布局次要为竖向瀑布流,因而本文所探讨的是竖向瀑布流
特点
竖向瀑布流布局次要有上面几种特点:
- 个别呈现在挪动端 H5 页面底部
- 次要以图片或视频为主
- 升高页面复杂度,节俭空间,能够包容更多内容
- 不规则展现,不会那么干燥,用户体验好
- 难以或者说不能滚动到页面最底部
不同于传统的分页,瀑布流因为以上这些特点个别被用在这些场景下:
举荐机制下的信息
即依据用户画像举荐或者经营人员举荐的信息大分类下的信息流
展现的信息有很多,它们的大分类都是雷同的,适宜用户不明确具体须要取得什么信息或商品的状况下各个信息或商品之间没有比拟强的相关性
和下面一条相似,展现的不是千遍一律的货色,绝对独立的信息或商品兴许能让用户意外挖掘到想要的货色
实现
一般来说次要分为 CSS 实现和 JS 实现
CSS 实现次要是用到一些专门的款式属性,实现起来简略,然而往往会有兼容性问题
JS 实现的办法则不存在这些问题,并且能实现比拟个性化的需要,然而实现起来比拟麻烦
column 多列布局办法
column 实现瀑布流次要依赖两个属性
column-count 属性是设置共有几列 <br/>
column-gap 属性是设置每列之间的距离
column 兼容性
代码
<style>
.pic {
column-count: 3;
column-gap: 5px;
}
.pic .item {
border: 1px solid #ccc;
margin-bottom: 5px;
}
.item img {width: 100%;}
</style>
<body>
<div class="pic">
<div class="item">
<!-- 获取 api 取到的图片地址 -->
<img src="" />
<div>001</div>
</div>
······
<div class="item">
<img src="" />
<div>008</div>
</div>
</div>
</body>
flex 弹性布局办法
flex 实现瀑布流须要给父元素设置为横向排列。而后通过设置 flex-flow: column wrap
使其换⾏
代码
<style>
.pic {
display: flex;
flex-flow: column wrap;
height: 100vh;
}
.item {
/* 每行展现 3 个 */
width: calc(100%/3 - 5px);
border: 1px solid #ccc;
margin-bottom: 5px;
}
.item img {width: 100%;}
</style>
<body>
<div class="pic">
<div class="item">
<!-- 获取 api 取到的图片地址 -->
<img src="" />
<div>001</div>
</div>
······
<div class="item">
<img src="" />
<div>008</div>
</div>
</div>
</body>
成果
能够发现图片排序程序是先垂直方向,而后才是程度方向的。column 多列布局和 flex 弹性布局办法实现的效果图最终类似
JS + 懒加载办法
在不思考兼容性或者没有非凡图片展现程序需要下,只是实现瀑布流的话下面两种计划是够用的。如果要实现一些个性化的需要的话,还是得用 JS
次要思路就是:
- 先将第一行排满
- 计算第一行的所有图片高度,将第二行第一张图放在第一行最矮的图片前面
- 进行玩步骤 2,从新计算以后所有列高度,防止步骤 2 增加实现后,该列高度还是最矮
残缺代码
<!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>JS 实现瀑布流 </title>
<style>
.item {
box-sizing: border-box;
border: 1px solid #ccc;
position: absolute;
/* 展现为三列,减去距离宽度 */
width: calc(100% / 3 - 5px);
}
.item img {width: 100%;}
</style>
</head>
<body>
<div id="pic">
<div class="item">
<img src="..." />
<div>001</div>
</div>
<!-- 残余图片,理论场景中应该应用 for 循环 -->
<div class="item">
<img src="..." />
<div>015</div>
</div>
</div>
</body>
<script>
var pic = document.getElementById('pic');
var items = pic.children;
// 相邻间距为 5 像素
var space = 5;
var picAmount = 15;
window.onload = function () {function getClient() {
return {
width: window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth,
height: window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight,
};
}
function getScrollTop() {
return document.documentElement.scrollTop ||
window.pageYOffset ||
document.body.scrollTop;
}
waterFall();
function waterFall() {var pageWidth = getClient().width;
var itemWidth = items[0].offsetWidth;
var columns = parseInt(pageWidth / (itemWidth + space));
var picList = [];
for (var i = 0; i < items.length; i++) {if (i < columns) {items[i].style.top = 0;
items[i].style.left = (itemWidth + space) * i + 'px';
picList.push(items[i].offsetHeight);
} else {
// 找到数组中最小高度的那一列,并拿到其下标
var minHeight = picList[0];
var index = 0;
for (var j = 0; j < picList.length; j++) {if (minHeight > picList[j]) {minHeight = picList[j];
index = j;
}
}
items[i].style.top = picList[index] + space + 'px';
items[i].style.left = items[index].offsetLeft + 'px';
// 操作列的高度 = 当前列本来高度 + 图片的高度 + 相邻的间距
picList[index] = picList[index] + items[i].offsetHeight + space;
}
}
}
window.onresize = function () {waterFall();
};
// 监听滚动事件,模仿懒加载
window.onscroll = function () {
// 如果滚动到的地位比以后显示的最初一个图片高,则申请新的图片
if (getClient().height + getScrollTop() >=
items[items.length - 1].offsetTop
) {
// 后续的新图片
var datas = [...];
for (var i = 0; i < datas.length; i++) {
picAmount += 1;
var div = document.createElement('div');
div.className = 'item';
div.innerHTML = `<img src="${datas[i]}" alt=""><div>0${picAmount}</div>`;
pic.appendChild(div);
}
waterFall();}
};
};
</script>
</html>
成果
不同于下面两个 css 实现的瀑布流,JS 实现的图片排序程序是先程度方向,而后才是垂直方向
总结
如果实现成果简略不思考兼容的的话能够抉择应用 CSS 实现;若要兼容老版本浏览器或者实现一些个性化的需要还是得用 JS 实现
当然除了上文说的这些办法以外,也能够应用第三方库 Masonry 实现