column-count 是最轻量的纯 css 瀑布流方案,适用于静态场景;动态需求必须用 js 或 masonry,因其支持图片加载监听、响应式重排与高性能定位。

纯 CSS 实现瀑布流相册,column-count 是最轻量、最易上手的方案,但仅适用于图片高度可预测、且不依赖 JS 交互的静态场景;真要兼容动态加载、响应式缩放或 hover 效果,必须引入 JavaScript 或第三方库(如 Masonry)。
用 column-count 快速搭出基础瀑布流
这是唯一不用写 JS 就能跑起来的原生方案,原理是把容器当成“多栏文本”,让子元素按列自动折行填充。
-
column-count设列数(如column-count: 3),column-gap控制列间距,break-inside: avoid防止单个.item被拆到两列 - 图片必须设
width: 100%,否则会撑破列宽;高度保持auto,由内容决定 - 不支持
:hover动画触发重排——悬停时图片拉伸会导致整列错位,视觉跳动明显 - 在 Safari 旧版本中,
column-count对flex或grid子项兼容性差,建议只用<div> + <code><img>原生结构.album { column-count: 3; column-gap: 12px; } .album .item { break-inside: avoid; margin-bottom: 12px; } .album img { width: 100%; height: auto; display: block; }为什么
flex或grid直接做不了真瀑布流CSS Grid 的
grid-template-rows: masonry还在实验阶段(Chrome 119+ 支持但需加-webkit-前缀),display: grid+grid-auto-flow: dense只能模拟等高块,不是真正按高度自动归位的瀑布流。-
grid列数固定后,所有行高取最大值,导致大量空白(尤其图文混排时) -
flex的flex-wrap: wrap按宽度折行,但无法控制“哪张图该落到哪一列底部”,必须靠 JS 计算最小列高 - 哪怕强行用
position: absolute+ JS 定位,滚动时重绘开销大,iOS 上容易掉帧
必须用 JS 时,选
Masonry还是手写最小列算法如果要支持图片懒加载、无限滚动或响应式列数切换,
Masonry是目前最稳的选择;手写最小列逻辑看似简单,但图片加载异步、窗口 resize、DOM 插入顺序都会引发布局抖动。-
Masonry内置imagesLoaded钩子,等图片尺寸确定后再布局,避免高度塌陷 - 它用
position: absolute+transform定位,比top/left性能更好,也规避了文档流干扰 - 手写时若直接用
offsetHeight获取高度,可能拿到 0(图片未加载完),必须监听load事件或用getBoundingClientRect() - 列数随屏幕变化时,
Masonry提供layout方法强制重排;手写需绑定resize并清空缓存列高数组
图片路径和容器宽度处理的坑
瀑布流对图片尺寸敏感,一个没设宽高的
<img>或一个未声明box-sizing: border-box的容器,都会让列宽计算失准。- 所有
.item外层容器必须设box-sizing: border-box,否则 padding/margin 会额外撑宽 - 图片路径失效时,
offsetHeight返回 0,Masonry会把它塞进第一列顶部,造成后续全部错位 - 用
vw或 % 设置容器宽度时,务必配合min-width,否则小屏下column-count: 3会压成一列还留大片空白 - 服务端返回的图片尺寸若含小数(如 482.3px),CSS 渲染会四舍五入,JS 计算列高时建议用
Math.floor统一取整
真正难的不是让图片“看起来像瀑布”,而是让它们在不同网络速度、不同设备像素比、不同图片加载时机下,始终稳定落位——这点上,
Masonry的健壮性远超手写逻辑,除非你明确知道每张图的原始尺寸且禁止懒加载。 -











