跳转到内容

瀑布流

刀刀

1/3/2025

0 字

0 分钟

方法实现

grid布局

第一种方法是通过 grid 布局实现纯 CSS 瀑布流效果。

这种方法的核心思想步骤为:

  1. 父容器设置为 grid 布局
  2. 设置网格布局的分布情况为4列,每列占一份
  3. 控制行高不保持一样,使用 masonry 变为砖石结构
  4. 添加缝隙
html
<template>
  <div class="water-fall">
    <div v-for="item in generateArticleRoutes" :key="item.path" >
      <img :src="item.meta.img" alt="">
    </div>
  </div>
</template>

<style lang="less" scoped>
.water-fall {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
  gap: 20px;

  div {
    width: 100%;
  }
}
</style>

分列调整布局

第二种方法是通过分列布局,然后调整图片盒子之间的间距实现纯 CSS 瀑布流效果。

这种方法的核心思想步骤为:

  1. 父盒子分为4列 column-count: 4,此时分为4列,盒子之间没有高度间隙
  2. 通过设置子盒子的内间距和 column-gap 调整子盒子每个之间的间隙
html
<template>
  <div class="water-fall">
    <div v-for="item in generateArticleRoutes" :key="item.path" >
      <img :src="item.meta.img" alt="">
    </div>
  </div>
</template>

<style lang="less" scoped>
.water-fall {
  column-count: 4;
  column-gap: 20px;
  grid-template-rows: masonry;
  gap: 20px;

  div {
    display: block;
    width: 100%;
    padding: 10px 0;
  }
}
</style>

flex布局

第三种方法是通过 flex 布局实现纯 CSS 瀑布流效果。

这种方法的核心思想步骤为:

  1. 为父容器设置一个固定的高度,并设置为 flex 布局
  2. 让盒子主轴方向变为纵轴排列 column
  3. 使用 flex-wrap 属性来允许子元素换行
  4. 为每一项子盒子设置百分比宽度,使其自适应容器宽度。比如希望一行4个元素,则子盒子宽度为 25%
html
<template>
  <div class="water-fall">
    <div v-for="item in generateArticleRoutes" :key="item.path" >
      <img :src="item.meta.img" alt="">
    </div>
  </div>
</template>

<style lang="less" scoped>
.water-fall {
  display: flex;
  flex-direction: column;
  height: 1250px;
  flex-wrap: wrap;

  div {
    width: 25%;
  }
}
</style>

此时有瀑布流的初步效果了。 初步效果

但是还有两个问题需要解决:

  1. 子盒子元素之间没有空隙,需要加上
  2. 子盒子图片排列和第二种情况一样,是竖向排列,需要改成横向排列

来看第一个问题,为每个容器图片之间添加间隙,这个使用 gappadding 就能实现。外层容器加个 X轴 overflow: hidden 隐藏掉一处部分和滚动条。

less
.water-fall {
  display: flex;
  flex-direction: column;
  height: 1250px;
  flex-wrap: wrap;
  gap: 11px; 
  padding: 11px; 
  overflow: hidden; 
}

来看第二个问题,竖向排列改为横向排列,可以画一张草图辅助理解。 草图 根据草图看第一列的数字,不难看出它们都有一个规律,就是 4n+1 ,以此类推第二列就是 4n+2 ,第三列就是 4n+3 ......使用 nth-child() 为符合要求的子盒子图片设置 order 排序即可实现。

less
div {
  &:nth-child(4n+1) { 
    order: 1; 
  } 
  &:nth-child(4n+2) { 
    order: 2; 
  } 
  &:nth-child(4n+3) { 
    order: 3; 
  } 
  &:nth-child(4n) { 
    order: 4; 
  } 
}

注意事项

分列布局为何设置padding以及取值多少

分列布局中,为每个子盒子设置 padding 是为了给每个子盒子添加间隙,使子盒子之间有间隔,如果设置外边距 margin ,会出现第一行图片没对齐的情况。

至于取值,内边距上下取值 column-gap 的一半,因为上下边距会有塌陷的效果;左右取值0,这样x轴就不会超出内容出现进度条。

flex 布局方法为什么要设为纵轴为主轴

flex 布局的盒子来说,会以主轴方向来决定盒子的默认宽度或高度。如果当前的主轴是横轴,则每个盒子、图片的宽度以自身的宽度渲染完,而整体父容器的高度会以当前最高的子盒子作为高度,高度就会出现留白。

主轴设为纵轴后,每个子盒子图片高度会渲染完,宽度会以最宽的子盒子作为宽度,这样就可以实现瀑布流的效果。

优劣比对

grid布局

优点:

  • 主要由 grid 布局实现,代码简单

缺点:

  • 有兼容影响,目前只能firefox浏览器适用,未来可期
  • 不是每个人都了解 grid

分列调整布局

优点:

  • 代码简洁,兼容性好,无兼容影响

缺点:

  • 方法冷门,不一定写的出来
  • 图片顺序不是从左到右,而是从上到下,对于部分功能需求不满足

flex布局

优点:

  • 主要由 flex 布局实现,操作简单
  • 无兼容影响,各个浏览器均适用

缺点:

  • 父容器需要设定死高度,依赖 flex 布局的换行实现,不够灵活
  • 需要手动设置 order 排序、 gappadding ,否则无法实现瀑布流效果

总体效果