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

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

特点

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

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

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

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

实现

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

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

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

column 多列布局方法

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

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

column-gap 属性是设置每列之间的间隔

column 兼容性

代码

  1. <style>
  2. .pic {
  3. column-count: 3;
  4. column-gap: 5px;
  5. }
  6. .pic .item {
  7. border: 1px solid #ccc;
  8. margin-bottom: 5px;
  9. }
  10. .item img {
  11. width: 100%;
  12. }
  13. </style>
  14. <body>
  15. <div class="pic">
  16. <div class="item">
  17. <!-- 获取 api 取到的图片地址 -->
  18. <img src="" />
  19. <div>001</div>
  20. </div>
  21. ······
  22. <div class="item">
  23. <img src="" />
  24. <div>008</div>
  25. </div>
  26. </div>
  27. </body>

flex 弹性布局方法

flex 实现瀑布流需要给父元素设置为横向排列。然后通过设置 flex-flow: column wrap 使其换⾏

代码

  1. <style>
  2. .pic {
  3. display: flex;
  4. flex-flow: column wrap;
  5. height: 100vh;
  6. }
  7. .item {
  8. /* 每行展示 3 个 */
  9. width: calc(100%/3 - 5px);
  10. border: 1px solid #ccc;
  11. margin-bottom: 5px;
  12. }
  13. .item img {
  14. width: 100%;
  15. }
  16. </style>
  17. <body>
  18. <div class="pic">
  19. <div class="item">
  20. <!-- 获取 api 取到的图片地址 -->
  21. <img src="" />
  22. <div>001</div>
  23. </div>
  24. ······
  25. <div class="item">
  26. <img src="" />
  27. <div>008</div>
  28. </div>
  29. </div>
  30. </body>

效果

可以发现图片排序顺序是先垂直方向,然后才是水平方向的。column 多列布局和 flex 弹性布局方法实现的效果图最终相似

JS + 懒加载方法

在不考虑兼容性或者没有特殊图片展示顺序需求下,只是实现瀑布流的话上面两种方案是够用的。如果要实现一些个性化的需求的话,还是得用 JS

主要思路就是:

  1. 先将第一行排满
  2. 计算第一行的所有图片高度,将第二行第一张图放在第一行最矮的图片后面
  3. 进行玩步骤 2,重新计算当前所有列高度,避免步骤 2 添加完成后,该列高度还是最矮

完整代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>JS实现瀑布流</title>
  8. <style>
  9. .item {
  10. box-sizing: border-box;
  11. border: 1px solid #ccc;
  12. position: absolute;
  13. /* 展示为三列,减去间隔宽度 */
  14. width: calc(100% / 3 - 5px);
  15. }
  16. .item img {
  17. width: 100%;
  18. }
  19. </style>
  20. </head>
  21. <body>
  22. <div id="pic">
  23. <div class="item">
  24. <img src="..." />
  25. <div>001</div>
  26. </div>
  27. <!-- 剩余图片,实际场景中应该使用for循环 -->
  28. <div class="item">
  29. <img src="..." />
  30. <div>015</div>
  31. </div>
  32. </div>
  33. </body>
  34. <script>
  35. var pic = document.getElementById('pic');
  36. var items = pic.children;
  37. // 相邻间距为5像素
  38. var space = 5;
  39. var picAmount = 15;
  40. window.onload = function () {
  41. function getClient() {
  42. return {
  43. width: window.innerWidth ||
  44. document.documentElement.clientWidth ||
  45. document.body.clientWidth,
  46. height: window.innerHeight ||
  47. document.documentElement.clientHeight ||
  48. document.body.clientHeight,
  49. };
  50. }
  51. function getScrollTop() {
  52. return document.documentElement.scrollTop ||
  53. window.pageYOffset ||
  54. document.body.scrollTop;
  55. }
  56. waterFall();
  57. function waterFall() {
  58. var pageWidth = getClient().width;
  59. var itemWidth = items[0].offsetWidth;
  60. var columns = parseInt(pageWidth / (itemWidth + space));
  61. var picList = [];
  62. for (var i = 0; i < items.length; i++) {
  63. if (i < columns) {
  64. items[i].style.top = 0;
  65. items[i].style.left = (itemWidth + space) * i + 'px';
  66. picList.push(items[i].offsetHeight);
  67. } else {
  68. // 找到数组中最小高度的那一列,并拿到其下标
  69. var minHeight = picList[0];
  70. var index = 0;
  71. for (var j = 0; j < picList.length; j++) {
  72. if (minHeight > picList[j]) {
  73. minHeight = picList[j];
  74. index = j;
  75. }
  76. }
  77. items[i].style.top = picList[index] + space + 'px';
  78. items[i].style.left = items[index].offsetLeft + 'px';
  79. // 操作列的高度 = 当前列原本高度 + 图片的高度 + 相邻的间距
  80. picList[index] = picList[index] + items[i].offsetHeight + space;
  81. }
  82. }
  83. }
  84. window.onresize = function () {
  85. waterFall();
  86. };
  87. // 监听滚动事件,模拟懒加载
  88. window.onscroll = function () {
  89. // 如果滚动到的位置比当前显示的最后一个图片高,则请求新的图片
  90. if (
  91. getClient().height + getScrollTop() >=
  92. items[items.length - 1].offsetTop
  93. ) {
  94. // 后续的新图片
  95. var datas = [...];
  96. for (var i = 0; i < datas.length; i++) {
  97. picAmount += 1;
  98. var div = document.createElement('div');
  99. div.className = 'item';
  100. div.innerHTML = `<img src="${datas[i]}" alt=""><div>0${picAmount}</div>`;
  101. pic.appendChild(div);
  102. }
  103. waterFall();
  104. }
  105. };
  106. };
  107. </script>
  108. </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. jQuery--筛选【查找函数】

    查找函数介绍 <A> <B> <C></C> <D></D> <E></E> <F>< ...

  2. Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?

    Redisson.Jedis.lettuce 等等,官方推荐使用 Redisson.

  3. 云计算:Ubuntu下Vue+Springboot前后端分离项目部署(多节点)

    一.机器准备 首先准备三台机器: 我是一台WINDOWS系统主机,在WINDOWS里的 VMware 中安装两台Ubuntu系统虚拟机 如果你的虚拟机只有 CentOS,可以参考这篇文章:https: ...

  4. Java基础学习之“二维数组”

    一.鄙人对二维数组的理解 二维数组就是由多个数组并列而成 二.举例 1.普通数组(一维数组)的图像格式 2.二维数组的图像格式 代码 1 @Test 2 public void xueXi(){ 3 ...

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

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

  6. vue入门文章

    本来想自己写一篇关于vue入门的文章.但是看到链接的文章后,觉得写得太详细了,实在有保存下来的必要.后面可能在这篇文章基础上,有所内容的增加. CSS预处理器 定义了一种新的专门的编程语言,编译后成正 ...

  7. webpack系列——webpack3导入jQuery的新方案

    本文的目的 拒绝全局导入jQuery!! 拒绝script导入jQuery!! 找到一种只在当前js组件中引入jQuery,并且使用webpack切割打包的方案! 测试环境 以下测试在webpack3 ...

  8. ES6-11学习笔记--类与继承

    ES5 中的类与继承: 类的定义: function People(name, age) { // this指向当前实例化对象 console.log(this); // 实例属性 this.name ...

  9. Python中使用正则表达式获取两个字符中间部分

    问题背景:当我们爬取网页信息时,对于一些标签的提取是没有意义的,所以需要提取标签中间的信息. 解决办法:用到了re包下的函数 方法1:用到了research()方法和group()方法 方法2:用到了 ...

  10. java静态方法和实例方法的区别

    静态方法(方法前冠以static)和实例方法(前面未冠以static)的区别  调用静态方法或说类方法时,可以使用类名做前缀,也可以使用某一个具体的对象名:通常使用类名.static方法只能处理sta ...