columns 是最轻量、兼容性最好的纯 css 瀑布流方案,支持 ie10+,但仅按文档流顺序填充、不支持高度优先分配,需配合 break-inside-avoid 防截断,且无法响应式自动切换列数。

纯 CSS 实现瀑布流,columns 是最轻量、兼容性最好、无需 JS 干预的方案——但它不支持按数据顺序逐行填充(比如 Pinterest 那种“高度最小列优先”),只适合静态内容或对排序无要求的场景。
用 columns 实现基础瀑布流(无 JS)
这是唯一能用纯 Tailwind 完成的瀑布流方式,本质是 CSS 多栏排版,浏览器原生支持,IE10+ 可用。
-
columns会把子元素按文档流顺序“从上到下、从左到右”填满各列,不是按高度动态分配,所以图片顺序和视觉顺序一致,但列高可能不均衡 - 必须配合
break-inside: avoid防止单个卡片被截断到两列,Tailwind 对应类是break-inside-avoid - 列数由
columns-3这类工具类控制,但实际列宽受容器宽度和column-gap影响,不是固定像素值 - 不支持响应式列数自动切换(比如小屏 2 列、大屏 4 列),得靠
sm:columns-2 md:columns-4手动写断点
<div class="columns-3 sm:columns-2 gap-4"> <div class="break-inside-avoid bg-gray-100 p-4">图片 1</div> <div class="break-inside-avoid bg-gray-200 p-4">图片 2</div> <div class="break-inside-avoid bg-gray-300 p-4">图片 3</div> </div>
为什么不能用 grid-cols-3 模拟瀑布流
Grid 的 grid-cols-3 是规则网格,所有行高取该行最高项,无法形成错落效果。即使搭配 grid-auto-flow: dense,也只影响 item 排序顺序,不会改变行高计算逻辑。
- 尝试
grid grid-cols-3 grid-auto-flow-row-dense:只是让空缺位置被后续 item 填充,但每行仍强制等高,视觉仍是“台阶式”,不是瀑布流 - 想用 Grid 实现真瀑布流,必须用
grid-template-columns: masonry(Chrome 115+ 支持),但目前 Safari / Firefox 完全不支持,Tailwind 也没提供对应工具类 - 别硬套
flex flex-wrap:Flex 会按行打包,同样无法跨行错位,且无法控制“哪一列先放”
需要动态排序?必须用 JS + 绝对定位
如果业务要求“第二张图插在当前最短列底部”(即 Masonry 行为),CSS 无解,只能手写 JS 计算每列当前高度并绝对定位。
- 核心逻辑:维护一个
columnHeights = [0, 0, 0]数组,每次插入新图时找最小值索引,top设为该列当前高度,left设为列起始横坐标,再更新该列高度 - Tailwind 在这里只负责基础样式(如
absolute、inset-0、w-full),布局计算完全脱离它 - 图片加载前高度未知?得监听
img.onload或用picturePreLoad: true延迟布局,否则初始位置全乱 - 别忘了给容器设
relative,否则absolute子项会相对于视口定位
移动端适配和性能陷阱
瀑布流在小屏上容易因列数过少导致单列过长,触达困难;列数过多又让图片太窄失去信息量。
- 列数别死写
columns-4,用响应式类如columns-1 sm:columns-2 md:columns-3 lg:columns-4 - 图片未设置宽高比时,加载瞬间会触发重排,建议提前用
aspect-video或内联style="aspect-ratio: 4/3"占位 -
columns在 iOS Safari 上对transform或position: sticky元素有渲染 bug,避免混用 - 超过 200 项时,
columns渲染性能明显下降,此时 JS 方案配合虚拟滚动更稳妥
真正麻烦的从来不是怎么写出来,而是决定要不要放弃纯 CSS —— 如果后端返回的数据顺序就是展示顺序,columns 够用;如果要按视觉高度动态调度,JS 定位绕不开,Tailwind 只是帮你少写几行 position: absolute。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











