grid-template-rows: masonry 是最轻量、语义正确、无需 JS 的原生响应式瀑布流方案,但仅 Chrome/Edge 支持,需用 @supports 降级为 grid-auto-flow: dense;禁用 column-count 因其破坏 DOM 顺序与可访问性;JS 仅用于图片加载、SSR 水合或动态重排等必要场景。

现代浏览器原生支持 grid-template-rows: masonry,这是目前最轻量、语义正确、无需 JS 的响应式瀑布流实现方式;但 Safari 和 Firefox 仍不支持,必须搭配 @supports 降级方案,否则在非 Chrome/Edge 下会退化为单列或错位。
用 grid-template-rows: masonry 写真正响应式模板
它不是“模拟”,而是浏览器原生按内容高度自动分列,DOM 顺序与视觉顺序完全一致,不影响 SEO、可访问性或打印样式。关键约束有三个:
- 容器必须同时声明
display: grid和grid-template-columns(如repeat(auto-fit, minmax(300px, 1fr)))),否则 Masonry 不生效 - 不能设置
grid-auto-flow: column或手动指定grid-row,否则破坏自动布局逻辑 - 子项内图片需预留宽高比空间,否则加载前高度为 0,导致 Masonry 初始计算错误——推荐用
aspect-ratio: 4/3或padding-top: 75%容器占位
@supports 降级到 grid-auto-flow: dense 的写法
Firefox 和 Safari 用户看到的是视觉接近的“伪瀑布流”:等宽列 + 高度错落 + 空隙回填。这不是妥协,而是安全 fallback:
- 必须用
auto-fit(不是auto-fill),否则小屏下生成空列,浪费空间 -
grid-auto-flow: dense必须显式声明,否则高卡片下方会留大片空白 - 避免在容器上设
overflow: hidden,否则跨行元素(如 span 多行文本)可能被截断 - Firefox 对
gap渲染不稳定,建议改用gap+margin-bottom组合控制间距
为什么别碰 column-count 做响应式瀑布流
它看起来简单,但实际项目中几乎必然翻车:
立即学习“前端免费学习笔记(深入)”;
- DOM 顺序是“先填满第 1 列,再填第 2 列”,导致第 4 个
<div class="item">出现在第 2 列顶部,而非第 1 列底部之后——键盘 tab、屏幕阅读器、SEO 全部错乱 - iOS Safari 中
column-count容器内的点击事件坐标偏移,按钮失灵率高 - Chrome 下
<img>默认display: inline,会在列底多出几像素空白,必须加display: block - 无法控制单张图片宽度,
width: 100%在列内会失效,常出现横向溢出
JS 方案只在必要时介入
纯 CSS 搞不定的场景才上 JS:比如卡片高度差异极大(图文混排 + 长文)、服务端渲染(SSR)首屏需精确布局、或滚动加载后必须增量重排。此时注意:
- 不要用
layout.reloadItems(),它强制重算全部项,性能爆炸;改用layout.appended(newItems) - 图片懒加载完成前,
getBoundingClientRect().height是 0,必须监听load事件后调用layout() - 若父容器有
transform或filter,Masonry 的position: absolute会定位偏移,需额外加contain: layout或改用相对定位方案 - 移动端 iOS Safari 中,
overflow: auto容器内卡片点击失效很常见,加-webkit-overflow-scrolling: touch并确保每张卡片有min-height: 1px
真正难的不是写出来,而是预判图片加载时机、处理 SSR 与客户端水合的错位、以及在 resize 和滚动中保持布局稳定——这些细节不写进 CSS,得靠 JS 补,但补之前,先确认是不是真绕不开。



















