瀑布流的实现思路是固定图片宽度, 根据图片比例再决定图片高度, 从而实现瀑布流

利用 Grid 实现

实现思路:

1.创建一个最小宽度固定, 最大宽度为 1fr 的列, 重复方式为自动填充 auto-fill

.waterfall {
  display: grid;
  grid-template-column: repeat(auto-fill, minmax(300px, 1fr));
}

这样, 图片的宽理论上就可以完整占满容器的宽了

瀑布流的目的是让各种不同比例的图片完全占满容器, 但实际上, 目前的效果还不能做到这点

虽然我们铺满了列空间, 但每行高度没有指定, grid 布局会自动按一行中最高的图片来作为行高度, 也就意味着每行都会因图片比例的不同而留有空隙

显示效果

2.设置行高

现在的问题是, 如何确定行的高度?

首先, 瀑布流的每一列所对应的行高都不同, 而这一列下的所有行高也会因图片比例的不同而不同, 看起来这个问题很棘手. 不过庆幸的是, grid 的子元素可以占据 1 个及以上的单元格, 我们可以将所有行高设置为 1px (将行高细分到最小单位), 让 grid 自行决定一张图片占据多少行也就是多少像素.

.waterfall {
  display: grid;
  grid-template-column: repeat(auto-fill, minmax(300px, 1fr));
  
  /* 细分行高到最小单位 */
  grid-auto-rows: 1px;
}

设置行高为 1px 后, 图片全变成一条线了, 因为现在行高固定为 1px 了, grid 默认每张图片的高度为 1px

我们现在要去告诉 grid 一张图片应该占据多少行, 即多少 px

首先, 先算出图片的宽高比, 再获取图片在容器中的实际宽度, 然后, 利用实际宽度乘以宽高比得到需要的高度

最后, 设置图片样式, 告诉 grid 需要占据多少行

const { width, height } = e.dataset;
const rowHeight = (e.clientWidth * (+height / +width)).toFixed(0);
image.style.setProperty('grid-row', `span ${rowHeight}`);

效果不错, 还差最后一步, 让 grid 决定如何填充空白单元格, 尽可能填满容器

显示效果

3.完善填充

实际上, 一行 css 即可完善填充, 利用 grid-auto-flow 自动布局算法, 充分利用显示空间

.waterfall {
  display: grid;
  grid-template-column: repeat(auto-fill, minmax(300px, 1fr));
  
  /* 细分行高到最小单位 */
  grid-auto-rows: 1px;

  /* grid 的 “稠密” 堆积算法 */
  grid-auto-flow: row dense;
}
最后修改:2026 年 04 月 24 日
如果觉得我的文章对你有用,请随意赞赏