瀑布流布局

268 阅读2分钟

瀑布流又称瀑布流式布局,是一种多列等宽不等高的一种页面布局方式。视觉表现为参差不齐的多栏布局。随着页面滚动条向下滚动,这种布局会不断加载数据并附加至当前的尾部。是一种多列等宽不等高的一种页面布局方式,用于图片比较复杂,图片尺寸比较复杂时可以使用的一种展示方式,这种展示方式可以使页面比较美观,让人有种错落有致的感觉。

以下实现一个简单的菜单栏的瀑布流布局:

//html
<template>
  <div class="pro-menu">
    <div class="menu-wrapper">
      <div v-for="item in menuList" :key="item.id" class="num">
        <div class="item">
          <span class="menu-name">{{item.name}}</span>
          <div v-for="(itx, ind) in item.spus" class="sub-item" :key="itx.name + ind">
            {{itx.name}}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
//js
menuLayout() {
    //父容器和每个菜单项的宽度
    let parentWidth = document.getElementsByClassName('menu-wrapper')[0].clientWidth
    let itemWidth = document.getElementsByClassName('num')[0].offsetWidth
    let gap = 20  //每个菜单的间隔
    let maxNum = Math.floor((parentWidth - itemWidth) / (itemWidth + gap)) + 1  //每行最多可展示几个菜单项

    let heightList = []
    // let minList = []
    let itemArr = document.getElementsByClassName('num')

    for (let i = 0; i < itemArr.length; i++) {
      //将第一行的菜单项高度放到heightList中,并设置第一行的菜单项的位置,
      if (i < maxNum) {
        heightList.push(itemArr[i].offsetHeight + gap)
        itemArr[i].style.top = gap + 'px'
        itemArr[i].style.left = (itemWidth + gap) * i + 'px'
      } else {
        let minHeight = heightList[0]
        let minIndex = 0
        //找出第一行中最小的高度及下标
        for (let j = 0; j < heightList.length; j++) {
          if (heightList[j] < minHeight) {
            minHeight = heightList[j]
            minIndex = j
          }
        }
        //将菜单项定位到某一位置
        itemArr[i].style.top = minHeight + gap + 'px'
        itemArr[i].style.left = (itemWidth + gap) * minIndex + 'px'
        //当菜单项定位到某列后,将对应的某列高度增加
        heightList[minIndex] = parseFloat(itemArr[i].style.top) + itemArr[i].offsetHeight
      }
      //避免定位改变导致的闪烁
      itemArr[i].style.opacity = 1
    }
    //调节最外层容器的高度
    let container = document.getElementsByClassName('pro-menu')[0]
    container.style.height = Math.max(...heightList) + 'px'
 }

最主要是保证父元素是相对定位,每个菜单项相对于父元素是绝对定位

//css
  .pro-menu {
    width: 400px;
    height: 1000px;
    background-color: red;
  }
  .menu-wrapper {
    position: relative;
    background-color: chartreuse;
    display: flex;
    flex-direction: column;
  }
  .num {
    width: 100px;
    position: absolute;
    background-color: aqua;
    border: 1px solid brown;
  }
  .menu-name {
    color: #000;
    font-weight: bold;
    font-size: 20px;
  }

效果图 image.png