页端瀑布流实现

196 阅读4分钟

页端瀑布流实现

缘起

最近有个二级页用到了瀑布流布局,然后就想了一下页端怎么实现,测试用到的图片都是网络图片,如有侵权删除

技术选型

移动端无脑 flex 布局,这个不用想了

flex布局 + flexwrap

首先想到的是这个方案,通过设置 flex-wrap: wrap ,让容器里面的项目自动换行,想起来好像没问题,试试

代码部分

<!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>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .container {
      display: flex;
      flex-wrap: wrap;
    }

    .item {
      width: calc((100% - 3px) / 2);
      background-color: #fff;
      padding-bottom: 16px;
    }

    .item:nth-child(2n) {
      padding-right: 0;
    }

    .img-item {
      width: 100%;
    }

    .item-text {
      padding: 0 12px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      color: rgba(0, 0, 0, 0.86);
      line-height: 22px;
      word-break: break-all;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
  </div>
</body>

</html>

结果

结果1

分析

  • 结果一出来不意外,同行的两个项目按照高的两个项目,设定了同行的高度,这个效果只是每一行的高度按项目最高的一个决定,并不是瀑布流想要实现的效果,这样想了一下,横排应该都不能实现这个效果
  • 既然横排不能保证上下两个项目的间隔是固定的,那就改成竖排
  • 如果列数是固定的话,所以有个比较简单的竖排方案,就例子来说,两列固定

flex 竖排方案

原理

用两个列,每个列展示项目

col1 col2
1    2
3    4
5

如上图所示,需要自己将数组拆成第一列和第二列,原理就这样了,实现起来也很简单

实现

<!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>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .container {
      display: flex;
    }
    .col {
      display: flex;
      flex-direction: column;
      width: calc((100% - 3px) / 2);
      padding-right: 3px;
    }
    .col:nth-child(2n) {
      padding-right: 0;
    }
    .item {
      background-color: #fff;
      padding-bottom: 16px;
    }
    .img-item {
      width: 100%;
    }
    .item-text {
      padding: 0 12px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      color: rgba(0,0,0,0.86);
      line-height: 22px;
      word-break: break-all;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="col">
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
    </div>
    <div class="col">
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词中文测试词中文测试词</div>
      </div>
      <div class="item">
        <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image" alt="" class="img-item">
        <div class="item-text">中文测试词中文测试词中文测试词中文测试词中文测试词</div>
      </div>
    </div>
  </div>
</body>
</html>

结果

结果2

可以看到已经是瀑布流了,这种是比较取巧的一种方案,适用于列数固定的瀑布流,宽度改变的话,图片的宽度也会改变,也算是一种比较简单的响应式,但是面对一些需要固定宽度的设计,这种方案会有问题

多栏布局实现瀑布流

多栏布局,容器中的项目排列顺序是从上到下,在从左到右

col1 col2 col3
1    5    9
2    6    10
3    7
4    8

容器属性

  • column-count: 设置共有几列
  • column-width: 设置每列宽度,列数由总宽度与每列宽度计算得出
  • column-gap: 设置列与列之间的间距
  • column-countcolumn-width 都设置的时候,哪个计算出来的列数小,按哪个计算

对于本例子,容器这样设置就好了

.container {
  column-count: 2;
  column-gap: 3px;
}

一是试一下,发现结果和预想中有一些差别,结果是这样的 结果3

问题

第一列最后一行的文字,在第二列顶部了,就像一个 item 内部被拆分了,有点不可思议,看了下 multi-column 布局会将其内的元素自动进行流动和平衡,尽可能保证每列的高度趋于相同,所以会将其内的文本阶段分布在两列内,但是这个不符合我们需要的效果

项目属性

  • break-inside

    • auto 默认,项目中的内容可以被划分到下一列
    • avoid 项目中的内容不可被划分
  • 要避免项目内内容被划分到不同列,只要设置 break-inside: avoid

最终实现代码

<!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>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .container {
      column-count: 2;
      column-gap: 3px;
    }

    .item {
      break-inside: avoid;
      background-color: #fff;
      padding-bottom: 16px;
    }

    .img-item {
      width: 100%;
    }

    .item-text {
      padding: 0 12px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      color: rgba(0, 0, 0, 0.86);
      line-height: 22px;
      word-break: break-all;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词中文测试词中文测试词中文测试词中文测试词中文测试词中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77b2cc29aa894116af74e2806991b786~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0431317073634a5e85564620e461bc7f~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
    <div class="item">
      <img
        src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba9b0242df34dc8aa3117861c4d4985~tplv-k3u1fbpfcp-watermark.image"
        alt="" class="img-item">
      <div class="item-text">中文测试词</div>
    </div>
  </div>
</body>

</html>

多列布局的不足

  • 要实现横排顺序的话,和 flex 方案一样,必须做一次数组转换,不然顺序不对

总结

页端实现方法还是比较多,用什么方案取决于自己的选择