创建瀑布流式猫猫图片库的多种方法

485 阅读1分钟

一起用代码吸猫!本文正在参与【喵星人征文活动】

瀑布流源于国外的一家图片分享网站Pinterest,该网站是通过看上去多列布局的方式展示图片,并且每一列高度有内容多少来决定形成列中的项高度不统一形成的层次不齐的砌墙效果。

瀑布流布局实现的多种方法

瀑布流布局看上去属于多列布局的一种,每列宽度相等但是高度不固定,从而形成的类似于砌墙效果。

基础布局介绍

多列瀑布流布局

通过创建相同宽度的多个列然后通过计算哪一列最低然后给列中添加元素来实现。

代码:

<!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>
      .falls-1 {
        text-align: center;
      }
      /* 设置4列,每列占25%宽度 */
      .falls-1 .columns {
        width: 25%;
        display: inline-block;
        vertical-align: top;
      }
      .columns img {
        width: 100%;
      }
  </style>
</head>
<body>
  <div class="falls-1" id="falls_1">
    <div class="columns">
      <img src="https://i.pinimg.com/474x/aa/f2/46/aaf246dbbdec567ead187202862b9157.jpg">
    </div>
    <div class="columns">
      <img src="https://i.pinimg.com/474x/c8/ae/ff/c8aeff2840e5216e312f79a0f17fbfdd.jpg">
    </div>
    <div class="columns">
      <img src="https://i.pinimg.com/474x/f9/9c/49/f99c49398a9d5278e7195a23a68c8473.jpg">
    </div>
    <div class="columns">
      <img src="https://i.pinimg.com/474x/5e/21/b5/5e21b5fa45cc04f8fd35537496ebe6d0.jpg">
    </div>
  </div>

  <script>
    let listArray = [];

    let cats = [
        'https://i.pinimg.com/474x/47/c2/75/47c2755c73390a1d8f1c1294dfa0351d.jpg',
        'https://i.pinimg.com/474x/c1/e3/4d/c1e34d9c2e8f9375f16af6bbeb549993.jpg',
        'https://i.pinimg.com/474x/5c/3b/20/5c3b20b38896d0fd3eec83b335b4a88a.jpg',
        'https://i.pinimg.com/474x/4f/f2/bf/4ff2bf81d323e6545171ba088f06805b.jpg',
        'https://i.pinimg.com/474x/d9/0e/49/d90e4938caa6a4f1ad139e062c985d54.jpg',
        'https://i.pinimg.com/474x/6b/79/8d/6b798dfdfe9ea7ea37b13ce59dc2cb86.jpg',
        'https://i.pinimg.com/474x/ec/24/92/ec2492547a647a3e4115a04222914e5d.jpg',
        'https://i.pinimg.com/474x/9e/cc/05/9ecc055e301ecc95c2320132eafb935b.jpg',
        'https://i.pinimg.com/474x/18/7b/b4/187bb4b8e0b0260f119861c52f3684fa.jpg',
        'https://i.pinimg.com/474x/09/9a/48/099a48ed4dd8aa5b298a06f5050c2d0e.jpg',
        'https://i.pinimg.com/736x/f1/13/7d/f1137d64842fbdfd431baa87995bf5a7.jpg',
        'https://i.pinimg.com/474x/c6/d2/18/c6d2189ae41651eba88b895f85c668a8.jpg',
        'https://i.pinimg.com/474x/c2/37/52/c2375242ef2547213eb90983b00120be.jpg',
        'https://i.pinimg.com/750x/8d/58/89/8d58893c41f49fe92502dc261a249bd5.jpg',
        'https://i.pinimg.com/474x/ee/00/20/ee0020e9d7586708083aecdb77be6293.jpg',
        'https://i.pinimg.com/474x/a3/66/ac/a366acda7c62c907f76daea769624638.jpg',
        'https://i.pinimg.com/474x/f7/81/5b/f7815b3cadca785828aa3a2b2c3f4dea.jpg',
        'https://i.pinimg.com/474x/82/06/27/820627b4cf3a90c036041c325e410925.jpg',
        'https://i.pinimg.com/474x/20/4a/16/204a1654f12844f6c14cc8c47eff28c7.jpg',
        'https://i.pinimg.com/474x/94/28/ea/9428ea711b2c42f3944ee601b9485148.jpg'
    ]
    for (let i = 0; i < 100; i++) {
      listArray.push(parseInt(Math.random() * (400 - 50 + 1) + 50, 10));
    }
    let falls_1 = document.getElementById('falls_1');
    let columns = falls_1.children;
    // 循环数据数组
    for(let x = 0; x<listArray.length; x++){

      let curColumns = columns[0];
      let item = document.createElement('div');
      let src = cats[Math.floor(Math.random() * cats.length)]

      item.innerHTML = `<img src="${src}" />`;
      // 通过判断哪一列最低然后获取最低的列
      for(let y = 1; y<columns.length; y++){

        if(curColumns.clientHeight>columns[y].clientHeight){

          curColumns = columns[y];
        }
      }
      // 把元素添加的最低的列
      curColumns.appendChild(item);
    }
  </script>
</body>
</html>

相对定位和绝对定位结合实现

通过元素的绝对定位来实现瀑布流相对来说比多列布局要复杂,因为他需要手动计算图片所在的位置,具体代码如下:

代码:

<!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>
  /*  这里我们通过inline-block来布局 */
  .falls-1 {
      position: relative;
  }
  /* 为了计算方便我们把所有的间距都在内部的元素中设置,
  这样一来我们就不用再计算定位的时候在去额外计算内外间距的距离了 */
  .falls-1 .item{
    position: absolute;
    top: 0;
    bottom: 10px;
    right: 10px;
    left: 10px;
    color:white;
  }
  .item img {
    box-sizing: border-box;
    padding: 10px;
    width: 100%;
  }
  </style>
</head>
<body>
  <div class="falls-1" id="falls_1">
  </div>

  <script>
    let cats = [
      'https://i.pinimg.com/474x/47/c2/75/47c2755c73390a1d8f1c1294dfa0351d.jpg',
      'https://i.pinimg.com/474x/c1/e3/4d/c1e34d9c2e8f9375f16af6bbeb549993.jpg',
      'https://i.pinimg.com/474x/5c/3b/20/5c3b20b38896d0fd3eec83b335b4a88a.jpg',
      'https://i.pinimg.com/474x/4f/f2/bf/4ff2bf81d323e6545171ba088f06805b.jpg',
      'https://i.pinimg.com/474x/d9/0e/49/d90e4938caa6a4f1ad139e062c985d54.jpg',
      'https://i.pinimg.com/474x/6b/79/8d/6b798dfdfe9ea7ea37b13ce59dc2cb86.jpg',
      'https://i.pinimg.com/474x/ec/24/92/ec2492547a647a3e4115a04222914e5d.jpg',
      'https://i.pinimg.com/474x/9e/cc/05/9ecc055e301ecc95c2320132eafb935b.jpg',
      'https://i.pinimg.com/474x/18/7b/b4/187bb4b8e0b0260f119861c52f3684fa.jpg',
      'https://i.pinimg.com/474x/09/9a/48/099a48ed4dd8aa5b298a06f5050c2d0e.jpg',
      'https://i.pinimg.com/736x/f1/13/7d/f1137d64842fbdfd431baa87995bf5a7.jpg',
      'https://i.pinimg.com/474x/c6/d2/18/c6d2189ae41651eba88b895f85c668a8.jpg',
      'https://i.pinimg.com/474x/c2/37/52/c2375242ef2547213eb90983b00120be.jpg',
      'https://i.pinimg.com/750x/8d/58/89/8d58893c41f49fe92502dc261a249bd5.jpg',
      'https://i.pinimg.com/474x/ee/00/20/ee0020e9d7586708083aecdb77be6293.jpg',
      'https://i.pinimg.com/474x/a3/66/ac/a366acda7c62c907f76daea769624638.jpg',
      'https://i.pinimg.com/474x/f7/81/5b/f7815b3cadca785828aa3a2b2c3f4dea.jpg',
      'https://i.pinimg.com/474x/82/06/27/820627b4cf3a90c036041c325e410925.jpg',
      'https://i.pinimg.com/474x/20/4a/16/204a1654f12844f6c14cc8c47eff28c7.jpg',
      'https://i.pinimg.com/474x/94/28/ea/9428ea711b2c42f3944ee601b9485148.jpg'
    ]
    // 随机生成100条数据
    let listArray = [];
    for (let i = 0; i < 100; i++) {
      listArray.push(parseInt(Math.random() * (400 - 80 + 1) + 80, 10));
    }
    // 这里表示列数
    let colLength = 4;
    let falls_1 = document.getElementById('falls_1');
    let colArray = [];
    // 通过父级的宽度和设置的列数来计算出每一项的宽度
    let itemW = falls_1.clientWidth/colLength;
    // 循环列数,初始化第一次元素的初始位置
    for(let x = 0; x<colLength;x++){
      colArray.push({
        t: 0, l: x*itemW});
    }
    // 循环数据
    for(let x = 0; x<listArray.length; x++){
      // 取第一个初始化数据
      let curPosition = colArray[0];
      // 然后通过循环判断哪一个数据最低
      for(let y = 1; y<colArray.length; y++){
        if(curPosition.t > colArray[y].t){
          curPosition = colArray[y];
        }
      }
      // 创建元素,并且给元素设置位置信息和宽高等信息
      let item = document.createElement('div');
      item.setAttribute('class','item');
      item.style.top = curPosition.t + 'px';
      item.style.left = curPosition.l + 'px';
      item.style.width = itemW + 'px';
      let src = cats[Math.floor(Math.random() * cats.length)]
      let img = document.createElement('img')
      img.src = src
      curPosition.height = img.height / img.width * itemW
      console.log(img.height)
      item.innerHTML = `<img src="${src}" />`;
      falls_1.appendChild(item);
      // 然后更新初始化中的数据,使下次循环时记录
      curPosition.t = curPosition.t + curPosition.height;
    }
  </script>
</body>
</html>

纯css实现瀑布流布局–columns

上边的两种方式都是css结合js来实现的,我们也可使只使用css就能实现瀑布流布局,columns是css中用来实现多列布局的属性,它可以把元素中的内容以相同宽度分成多列来呈现,我们可以通过此特性来实现瀑布流效果。

<!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>
      .falls-1 {
        text-align: center;
      }
      /* 设置4列,每列占25%宽度 */
      .falls-1 .columns {
        column-count: 3;
        vertical-align: top;
      }
      .columns img {
        width: 100%;
      }
  </style>
</head>
<body>
  <div class="falls-1" id="falls_1">
    <div class="columns"></div>
  </div>

  <script>
    let listArray = [];

    let cats = [
        'https://i.pinimg.com/474x/47/c2/75/47c2755c73390a1d8f1c1294dfa0351d.jpg',
        'https://i.pinimg.com/474x/c1/e3/4d/c1e34d9c2e8f9375f16af6bbeb549993.jpg',
        'https://i.pinimg.com/474x/5c/3b/20/5c3b20b38896d0fd3eec83b335b4a88a.jpg',
        'https://i.pinimg.com/474x/4f/f2/bf/4ff2bf81d323e6545171ba088f06805b.jpg',
        'https://i.pinimg.com/474x/d9/0e/49/d90e4938caa6a4f1ad139e062c985d54.jpg',
        'https://i.pinimg.com/474x/6b/79/8d/6b798dfdfe9ea7ea37b13ce59dc2cb86.jpg',
        'https://i.pinimg.com/474x/ec/24/92/ec2492547a647a3e4115a04222914e5d.jpg',
        'https://i.pinimg.com/474x/9e/cc/05/9ecc055e301ecc95c2320132eafb935b.jpg',
        'https://i.pinimg.com/474x/18/7b/b4/187bb4b8e0b0260f119861c52f3684fa.jpg',
        'https://i.pinimg.com/474x/09/9a/48/099a48ed4dd8aa5b298a06f5050c2d0e.jpg',
        'https://i.pinimg.com/736x/f1/13/7d/f1137d64842fbdfd431baa87995bf5a7.jpg',
        'https://i.pinimg.com/474x/c6/d2/18/c6d2189ae41651eba88b895f85c668a8.jpg',
        'https://i.pinimg.com/474x/c2/37/52/c2375242ef2547213eb90983b00120be.jpg',
        'https://i.pinimg.com/750x/8d/58/89/8d58893c41f49fe92502dc261a249bd5.jpg',
        'https://i.pinimg.com/474x/ee/00/20/ee0020e9d7586708083aecdb77be6293.jpg',
        'https://i.pinimg.com/474x/a3/66/ac/a366acda7c62c907f76daea769624638.jpg',
        'https://i.pinimg.com/474x/f7/81/5b/f7815b3cadca785828aa3a2b2c3f4dea.jpg',
        'https://i.pinimg.com/474x/82/06/27/820627b4cf3a90c036041c325e410925.jpg',
        'https://i.pinimg.com/474x/20/4a/16/204a1654f12844f6c14cc8c47eff28c7.jpg',
        'https://i.pinimg.com/474x/94/28/ea/9428ea711b2c42f3944ee601b9485148.jpg'
    ]
    for (let i = 0; i < 100; i++) {
      listArray.push(parseInt(Math.random() * (400 - 50 + 1) + 50, 10));
    }
    let falls_1 = document.getElementById('falls_1');
    let columns = falls_1.children;
    // 循环数据数组
    for(let x = 0; x<listArray.length; x++){

      let curColumns = columns[0];
      let item = document.createElement('div');
      let src = cats[Math.floor(Math.random() * cats.length)]

      item.innerHTML = `<img src="${src}" />`;
      curColumns.appendChild(item);
    }
  </script>
</body>
</html>