纯 css grid 无法实现真正瀑布流,因 grid-template-rows: masonry 仅实验性支持且兼容性差;grid-auto-flow: dense 不是瀑布流因其只填空不重排;当前最稳方案是 grid-auto-flow: column 配合 js 动态分配元素至最短列并更新列高。

纯 CSS Grid 无法实现真正意义上的瀑布流,grid-template-rows: masonry 虽是标准解法,但目前仅 Chrome 117+ / Edge 116+ / Firefox Nightly / Safari 17.4+ 实验性支持,主流稳定版 Safari 和 Firefox 完全不识别——写上去等于白写,部分浏览器甚至渲染空白。
为什么 grid-auto-flow: dense 不是瀑布流
它只负责“填空”,不是“重排”。你得先手动给每个 .item 设好 grid-row-start 和 grid-row-end,它才去补那些被跳过的格子;而瀑布流要求元素自动下坠到最短列。Grid 的轨道是静态的,dense 不会动态拉伸列高,也不会移动已定位的元素。删掉它反而更可控。
用 grid-auto-flow: column + JS 是当前最稳方案
Grid 控制列宽与间距,JS 负责把每个元素塞进当前最短列,并更新列高记录:
- 容器设
grid-auto-flow: column,列数由grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))控制 - JS 遍历所有
.item,用getBoundingClientRect().height获取真实高度(比offsetHeight更准,避开渲染抖动) - 维护数组
columns = [0, 0, 0]记录每列当前总高,每次插入前找最小值索引,插入后更新该列高度 - 插入方式选
appendChild比设order更可靠:后者依赖渲染顺序,resize 后容易错位;前者直接改 DOM 位置,重排确定
响应式重排必须防抖 + 监听容器而非窗口
只监听 window.resize 是错的——列数变化取决于容器宽度,不是视口:
- 用
ResizeObserver监听 Grid 容器的宽度变化 - 变化触发后,用
setTimeout(, 0)或requestAnimationFrame延迟执行重排,等布局稳定再算列高 - 图片加载完成(
img.onload)或懒加载触发后,也得重新跑一遍分配逻辑,否则高度不准导致错位
真正麻烦的从来不是怎么写第一版,而是图片异步加载、字体回流、用户缩放、SSR 首屏直出这些叠加起来的细节——它们不报错,但会让瀑布流看起来“歪了”或者“卡住”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











