column-count 是目前唯一真正按列高自动分配、无需 JS 且原生支持的纯 CSS 瀑布流方案;grid 仅能实现视觉近似,本质非真瀑布流,因 grid-auto-flow: dense 不跨行比较列高,无法动态填最短列。

纯 CSS 实现瀑布流,column-count 是目前唯一真正按列高自动分配、无需 JS 且浏览器原生支持的方案;grid 本身不支持真瀑布流逻辑,所谓“Grid 瀑布流”只是视觉近似,本质是等宽多列 + 密集填充,容易在高度差异大时留白或错位。
为什么 column-count 能做到“自动填最短列”
它不是靠 DOM 顺序渲染,而是把整个容器内容当作文本流,由浏览器排版引擎按列高均衡原则切分——第 1 列高了,下一项就优先塞进第 2 列。这个行为是原生的、无 JS 干预的。
- 必须给每个直接子项加
break-inside: avoid(Firefox 加-moz-break-inside: avoid,iOS Safari 13 及更早加-webkit-column-break-inside: avoid),否则卡片会被从中间劈开 -
column-gap推荐用px或rem,别用百分比(部分浏览器解析不稳定) - 容器需有明确高度或
max-height,否则在某些场景下会退化为单列 -
column-fill: balance显式声明能改善列高一致性,尤其内容较少时;但 iOS Safari 对它的支持仍不稳定,别强依赖
为什么 grid 写不出真瀑布流
grid-auto-flow: dense 不等于“自动插最短列”。它只允许短元素填补前面长元素留下的空隙,前提是这些空隙已在当前行中存在;它不会跨行重排、也不会动态比较各列当前高度。
- 写
grid-template-columns: repeat(3, 1fr)+grid-auto-flow: dense,结果是每行强制填满 3 个,完全不是瀑布流 - 想接近效果,得配合
grid-auto-rows: 10px(仅占位)+grid-row-end: span X手动控制跨行数,但必须预知高度或靠 JS 注入 -
grid-template-rows: masonry目前仅 Chrome 116+ 和 Safari 17.4+ 支持,且需@supports守卫,生产环境不可依赖 - Grid 的重绘成本更高:内容增删或 resize 时可能触发整网格重计算,长列表滚动易抖动
column-count 和 grid 响应式切换时的真实陷阱
两者渲染逻辑根本不同:column-count 按文档流顺序“垂直切段”,grid(尤其是 dense)按 DOM 顺序“动态插空”。混用媒体查询硬切,会导致视觉跳变、焦点丢失、SEO 顺序错乱。
立即学习“前端免费学习笔记(深入)”;
- 别写
@media (max-width: 768px) { .list { column-count: 2; } }同时又在大屏用 Grid —— DOM 顺序和渲染顺序会彻底错位 - 如果必须响应式,统一用
column-count阶梯降级(如 4 → 3 → 2 → 1),或统一用 Grid +@container(需启用 container queries) - 移动端双栏慎用
column-count:第 1 个卡片在左栏顶部,第 2 个就在右栏顶部,对时间线类内容割裂感极强 - 图片类瀑布流,
column-count更稳;但若卡片含 hover 动画、表单或需要精确跨列(如广告位占两列),Grid 是唯一选择
真正难的不是写哪几行 CSS,而是接受一个事实:纯 CSS 瀑布流没有银弹。column-count 看似简单,但 break-inside 兼容性、iOS 渲染偏差、可访问性问题都得实测;grid 看似可控,却要直面 dense 模式的语义断裂和响应式断点一变全崩。选哪个,取决于你愿为“列高均衡”让渡多少交互自由度,又愿为“DOM 顺序正确”承担多少维护成本。


















