什么?.....你还不知道瀑布流式布局?那赶快来看看吧!

1,085 阅读5分钟

开篇

瀑布流式布局(WaterFallLayouts)

  瀑布流式布局是一种流行的网页设计布局方式,适用于展示宽度一致但高度不一致的图片等内容。以图片展示为例,简单来说:若干张图片先排满第一行,当一行排满后,新的图片会紧接着上一行高度最小的那一列开始在下一行显示,从而形成了参差不齐、视觉上类似瀑布流水效果的布局。

如图:

image.png

实质上,瀑布流式布局方式有以下特点:

多列布局:页面被划分为多个等宽的列,每列独立填充内容。

动态高度:各列中的内容块(如图片、文章摘要等)高度不固定,依据内容自适应,使得列的高度各不相同。

逐行填充:内容逐个添加到当前最短的列中,以保持页面整体的平衡感和视觉流畅性。

无限滚动或分页加载:随着用户滚动页面,更多的内容会动态加载并添加到布局的尾部,提供了良好的用户体验和持续的浏览体验。

实际运用场景

  瀑布流布局最早因图片分享网站Pinterest的使用而广为人知,之后被广泛应用于各类网站和应用中。我们来看看生活中的例子:

image.png

7935a44c8b8e6baa072641318af4d6d.jpg 66db165744f72d470edc7b58f811699.jpg

许多社交APP中都如此推崇这一布局方式,自然是因为这种布局方式好处多多,不过这里不加赘述。我们直接进入到思路分析,开始手搓。

此处是需要用到的html css代码:

    <style>
    * {
        margin: 0;
        padding: 0;
      }

      #container {
        position: relative;
        width: auto;
      }

      .box {
        /*块级*/
        float: left; /*从左往右排列*/
        padding: 5px;
      }

      .box-img {
        width: 150px;
        padding: 5px;

      }

      img {
        width: 100%;
        /*高不需要设,会自动按比例缩放*/
      }
    </style>

  <body>
    <div id="container">
      <div class="box">
        <div class="box-img">
          <img src="./img/1.jpg" alt="转存失败,建议直接上传图片文件">
        </div>
      </div>
  </body>

JS部分实现思路

  1. 获取浏览器窗口的宽度screenWidth
  var screenWidth = window.innerWidth;

2.获取图片宽度Width(固定),计算一行能放下几张图片

  var imgWidth = cChild[0].offsetWidth;
  var num = Math.floor(screenWidth / imgWidth);
  //设置当前photos的父容器宽度
  cParent.style.width = `${imgWidth * num}px`;

3.将第一行每一列图片的高度Height放入数组

  for (var i = 0; i < cChild.length; i++) {
    if (i < num) {
      boxHeightArr.push(cChild[i].offsetHeight); //第一行每一列图片所在box的高度
    }
  }

4.根据每一列的高度,按从小到大的顺序摆放后面几行的图片

  for (var i = 0; i < cChild.length; i++) {
    if (i < num) {
      boxHeightArr.push(cChild[i].offsetHeight);   
    }else{
      //找出最矮列的高度
      var minHeight = Math.min(...boxHeightArr) //...解构
      //找出高度最小列的下标
      var minIndex = boxHeightArr.indexOf(minHeight) 
      //设置图片的摆放位置
      cChild[i].style.position = 'absolute'
      cChild[i].style.top = minHeight + 'px'
      cChild[i].style.left = imgWidth*minIndex + 'px'
      //更新这一列的高度
      boxHeightArr[minIndex] = boxHeightArr[minIndex] + cChild[i].offsetHeight
    }
  }

5.将上述代码放入函数体,查看效果

//此处传入的分别是id名和类名
imgLocation("container", "box");

image.png

短短几步,大体上就实现了预期的排列效果**,快动手试试吧!

优化部分

  光看效果确实不错,不过在实际体验后,不难发现,只是前面的部分代码还不足以满足用户的动态操作,主要体现在以下方面:

一、当往左减小浏览器窗口宽度时,右边的图片会被隐藏?

image.png

这个问题,观察代码分析不难知道,js的代码并未监控浏览器页面的一个缩放行为,自然不能够动态变化图片排列,我们只需要加上部分代码即可。

function resize(){
  imgLocation("container", "box");
}
window.addEventListener('resize',resize)

二、当往左减小浏览器窗口宽度后,继续向右还原其宽度,部分图片练成了“隐身术”?

image.png

而这个这个bug的原因在于:当浏览器窗口变宽时,已经移出可视区域的图片应当重新回到流中合适的位置。为了解决这个问题,我们需要相应地调整所有图片的位置。

  //排列前确保图片定位的参数为空
  for(var i = 0; i < cChild.length;i++){
    cChild[i].style.position = ''
    cChild[i].style.top =  ''
    cChild[i].style.left = ''
  }
解决了这些问题,至此,就是这个瀑布流布局方式的简单示例。

总结

瀑布流布局方式的实现其实不难,但是细节也需要注意,实际开发的情况更加复杂,我们可能需要注意以下方面:

1. 优化图片加载与布局

  • 懒加载:对于瀑布流布局,图片较多时可以采用懒加载技术,即滚动到可视区域时才加载图片,这有助于提高页面首次加载速度。
  • 图片尺寸预加载:在自己的项目中,可以通过JavaScript预加载图片尺寸,以便更快地计算布局,减少页面重排重绘。

2. 优化布局算法

  • 考虑图片的实际尺寸:在计算布局时,除了基于屏幕宽度和图片宽度计算列数,还应该考虑图片的实际尺寸(尤其是高度),以避免在窗口缩放时产生过多的空白或重叠。

3. 测试与兼容性

  • 跨浏览器测试:确保在不同浏览器和设备上都能正常工作,特别注意一些老版本浏览器可能对CSS3特性支持不足。
  • 触摸设备友好:考虑到移动设备用户,确保触控操作流畅,布局在各种屏幕尺寸和方向上都能良好展示。

本人拙见,若有错误,敬请指正