Chrome 116+ 和 Edge 116+ 支持 grid-template-rows: masonry 实现真瀑布流,但 Safari 和 Firefox 完全不支持;需配合 grid-template-columns、子项高度可预测、禁用 overflow: hidden,并手动用 @supports 编写降级方案。

Chrome 116+ 和 Edge 116+ 可以直接用 grid-template-rows: masonry 实现真瀑布流,但 Safari 和 Firefox 完全不支持——别在生产环境里当它已普及。
用 grid-template-rows: masonry 的前提条件
这个特性看着极简,但实际运行非常“娇气”:
- 必须配合
grid-template-columns使用,不能只写grid-template-rows: masonry单独生效 - 每个子项高度必须可预测:浏览器不会等图片加载完再计算布局,
height: auto或未设aspect-ratio的<img>会按 0 高度排列,全部堆顶 - 不支持
justify-content: center或align-items对齐控制,列内默认左对齐、顶部对齐 - 容器不能有
overflow: hidden,否则跨多行的卡片会被截断
降级 fallback 必须手动写 @supports
不能指望浏览器自动回退。必须显式包裹:
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-flow: dense;
}
@supports (grid-template-rows: masonry) {
.masonry {
grid-template-rows: masonry;
}
}
注意:@supports 里必须写完整声明(带值),只写 @supports (grid-template-rows) 不会命中。
立即学习“前端免费学习笔记(深入)”;
降级方案中,grid-auto-rows 建议设为固定值(如 200px),再配合 grid-row-end: span X 控制跨行——但这个 X 得靠 JS 算,纯 CSS 拿不到真实高度。
图片加载导致布局塌陷的根源和解法
所有“瀑布流一滚动就跳”的问题,90% 出在这里:DOM 渲染时 <img> 还没加载,getBoundingClientRect().height 是 0,JS 算出的跨行数全是 1。
- 最稳做法:服务端或构建时把缩略图宽高写进 HTML,例如
<img src="x.jpg" width="300" height="450"> - 次选:用
aspect-ratio: 4/3+width: 100%,不依赖 JS,且兼容性比 Masonry 好得多 - 禁用
loading="lazy"不现实,但可配合占位:给<img>外层加min-height: 200px,或用padding-bottom: 75%配合height: 0
动态追加新卡片时,别调 layout.reloadItems()
如果你用了 Masonry.js 或类似库,新增卡片后:
- 用
layout.appended(newElements)—— 只重排新增项,性能好 - 避免
layout.reloadItems()—— 它强制清空并重算全部项位置,卡顿明显,尤其在无限滚动场景下 - 确保新元素 DOM 已插入、且
<img>的width/height或aspect-ratio已就位,再调用appended
真正难的不是写 layout 逻辑,而是让每张图的高度在 JS 执行前就“确定”——这一步漏了,后面所有优化都是补救。



















