移动端瀑布流布局是一种比较流行的网页布局方式,视觉上来看就是一种像瀑布一样垂直落下的排版。每张图片并不是显示的正正方方的,而是有的长有的短,呈现出一种不规则的形状。但是它们的宽度通常都是相同的

因为移动端瀑布流布局主要为竖向瀑布流,因此本文所探讨的是竖向瀑布流

特点

竖向瀑布流布局主要有下面几种特点:

  • 一般出现在移动端 H5 页面底部
  • 主要以图片或视频为主
  • 降低页面复杂度,节省空间,可以容纳更多内容
  • 不规则展示,不会那么枯燥,用户体验好
  • 难以或者说不能滚动到页面最底部

不同于传统的分页,瀑布流因为以上这些特点一般被用在这些场景下:

  • 推荐机制下的信息 即根据用户画像推荐或者运营人员推荐的信息
  • 大分类下的信息流 展示的信息有很多,它们的大分类都是相同的,适合用户不明确详细需要获得什么信息或商品的情况下
  • 各个信息或商品之间没有比较强的相关性 和上面一条类似,展示的不是千遍一律的东西,相对独立的信息或商品也许能让用户意外发掘到想要的东西

实现

一般来说主要分为 CSS 实现和 JS 实现

CSS 实现主要是用到一些专门的样式属性,实现起来简单,但是往往会有兼容性问题

JS 实现的方法则不存在这些问题,并且能实现比较个性化的需求,但是实现起来比较麻烦

column 多列布局方法

column 实现瀑布流主要依赖两个属性

column-count 属性是设置共有几列

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

主要思路就是:

  1. 先将第一行排满
  2. 计算第一行的所有图片高度,将第二行第一张图放在第一行最矮的图片后面
  3. 进行玩步骤 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 实现

手摸手,带你实现移动端H5瀑布流布局的更多相关文章

  1. 手摸手带你学移动端WEB开发

    HTML常用标签总结 手摸手带你学CSS HTML5与CSS3知识点总结 手摸手带你学移动端WEB开发 好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/Ro ...

  2. 【转】手摸手,带你用vue撸后台 系列二(登录权限篇)

    前言 拖更有点严重,过了半个月才写了第二篇教程.无奈自己是一个业务猿,每天被我司的产品虐的死去活来,之前又病了一下休息了几天,大家见谅. 进入正题,做后台项目区别于做其它的项目,权限验证与安全性是非常 ...

  3. 【转】手摸手,带你用vue撸后台 系列三(实战篇)

    前言 在前面两篇文章中已经把基础工作环境构建完成,也已经把后台核心的登录和权限完成了,现在手摸手,一起进入实操. Element 去年十月份开始用vue做管理后台的时候毫不犹豫的就选择了Elemen, ...

  4. 【转】手摸手,带你用vue撸后台 系列一

    前言 说好的教程终于来了,第一篇文章主要来说一说在开始写业务代码前的一些准备工作吧,但这里不会教你webpack的基础配置,热更新怎么做,webpack速度优化等等,有需求的请自行google. 目录 ...

  5. 手摸手带你理解Vue的Computed原理

    前言 computed 在 Vue 中是很常用的属性配置,它能够随着依赖属性的变化而变化,为我们带来很大便利.那么本文就来带大家全面理解 computed 的内部原理以及工作流程. 在这之前,希望你能 ...

  6. 【手摸手,带你搭建前后端分离商城系统】03 整合Spring Security token 实现方案,完成主业务登录

    [手摸手,带你搭建前后端分离商城系统]03 整合Spring Security token 实现方案,完成主业务登录 上节里面,我们已经将基本的前端 VUE + Element UI 整合到了一起.并 ...

  7. 【转】手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)

    前言 做这个 vueAdmin-template 的主要原因是: vue-element-admin 这个项目的初衷是一个vue的管理后台集成方案,把平时用到的一些组件或者经验分享给大家,同时它也在不 ...

  8. 原创 | 手摸手带您学会 Elasticsearch 单机、集群、插件安装(图文教程)

    欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...

  9. 浅谈Java中的Condition条件队列,手摸手带你实现一个阻塞队列!

    条件队列是什么?可能很多人和我一样答不出来,不过今天终于搞清楚了! 什么是条件队列 条件队列:当某个线程调用了wait方法,或者通过Condition对象调用了await相关方法,线程就会进入阻塞状态 ...

随机推荐

  1. 面试问题之操作系统:Linux下进程的内存结构

    转载于:http://www.hqj.com/news/emb184.htm Linux操作系统采用虚拟内存管理技术,使得每个进程都有各自互不干涉的进程地址空间.该地址空间是大小为4GB的线性虚拟空间 ...

  2. mybatis-03-一对多关系映射(附源码)

    sb_mybatis /* Navicat MySQL Data Transfer Source Server : 阿里云 Source Server Version : 50724 Source H ...

  3. 搞懂高并发性能指标:QPS、TPS、RT、吞吐量

      一.QPS,每秒查询 QPS:Queries Per Second意思是"每秒查询率",是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的 ...

  4. CSS中宽度与高度

    div的高度 div由的高度是由它里面的字体乘以字体建议的行高确定,跟这个字体大小没有关系(不同字体相同字体大小,会影响div的高度.)如过明确告诉浏览器行高,div高度就是行高. 文字两端对齐: 文 ...

  5. 块级格式化上下文(BFC)

    一.什么是BFC 具有BFC属性的元素也属于普通流定位方式,与普通容器没有什么区别,但是在功能上,具有BFC的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且具有普通容 ...

  6. 在微信小程序中绘制图表(part2)

    本期大纲 1.确定纵坐标的范围并绘制 2.根据真实数据绘制折线 相关阅读:在微信小程序中绘制图表(part1)在微信小程序中绘制图表(part3) 关注我的 github 项目 查看完整代码. 确定纵 ...

  7. canvas菜鸟基于小程序实现图案在线定制功能

    前言 最近收到一个这样的需求,要求做一个基于 vue 和 element-ui 的通用后台框架页,具体要求如下: 要求通用性高,需要在后期四十多个子项目中使用,所以大部分地方都做成可配置的. 要求做成 ...

  8. jsp基础、el技术、jstl标签、javaEE的开发模式

    一.jsp技术基础 1.jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%=java变量或表达式> ...

  9. QGIS源码编译步骤详解——官方新方案

    目录 源码下载 环境下载 Cygwin64 OSGeo4W CMAKE Visual Studio 2017 环境配置 配置 编译   方案详细可见源码文件中INSTALL.md. 源码下载   QG ...

  10. window.history.go(-1);后退不刷新问题 移动端

    在后退的界面上添加 判断是否是返回window.addEventListener('pageshow', function (e) {    if(e.persisted || (window.per ...