真瀑布流无法靠flex-wrap或grid-template-columns实现,因二者不按列高分配元素;column-count需配max-height、break-inside: avoid及直系子元素等硬条件;JS方案须用offsetHeight维护列高数组并同步onload与resize事件。

移动端瀑布流不能靠 flex-wrap: wrap 或 grid-template-columns: repeat(2, 1fr) 实现“真交错”,因为它们不按列高分配元素,只会顺序填行或列——第二张图永远在第一张下方,留白不可避免。
用 column-count 做轻量级瀑布流(适合静态图+服务端渲染)
这是目前兼容性最好、零 JS、首屏即生效的方案,但必须满足三个硬条件,否则页面会单列、图片被截断、最后一列空着:
-
column-count必须配合容器的max-height(不能只写height: auto),否则浏览器认为空间无限,退化为 1 列 - 每个直接子元素(如
.item)必须加break-inside: avoid,且补全前缀:-webkit-column-break-inside: avoid和-moz-break-inside: avoid -
.item必须是瀑布流容器的**直系子节点**,中间不能嵌套 wrapper 层;img要设width: 100%; height: auto;,禁用固定 px 宽高 - 图片加载前高度为 0,会导致错位——用
aspect-ratio: 4/3预留空间,或服务端传宽高生成内联style="padding-top: 75%;"
用 JavaScript 手动维护列高数组(适合滚动加载+动态插入)
这是 Pinterest 风格的核心逻辑,关键不是“定位”,而是“每次插入前找 Math.min() 对应的列索引”。但新手常在这里翻车:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 读取元素高度必须用
offsetHeight(含 padding/border),不能用clientHeight(不含 border)或getBoundingClientRect().height(可能含 margin) -
img.onload触发后,不能立刻重排整个容器——先存高度到item.dataset.height = img.offsetHeight,等所有图片加载完再批量更新列高数组 -
window.resize时必须清空并重建列高数组,且要做防抖:只在宽度变化 > 1px 时才触发,否则旧高度残留导致后续元素全塞进同一列 - 不要用
display: flex或position: absolute包裹列容器——它们会让offsetHeight失效或脱离文档流
别碰 grid-auto-flow: dense 当瀑布流用
它只是视觉错觉,不是列高驱动。常见错误是以为开了 dense 就能自动填空,结果发现底部大片空白、DOM 顺序和视觉顺序严重错位:
-
grid-auto-flow: dense不感知列当前总高度,只按 DOM 顺序填完一行后回头插空,不会把第 5 个 item 插入第 2 列顶部空隙 - 必须配
grid-auto-rows(如200px)作为占位基准,设太小(10px)矮卡片塌缩,设太大(400px)又留白 - 动态插入新 item 时,整网格可能重计算,长列表下帧率抖动明显;移动端低端机尤其卡顿
- Firefox 对
gap在dense模式下的渲染有历史 bug,稳妥做法是用gap: 1rem+margin-bottom: 1rem+:last-child { margin-bottom: 0 }
真正难的从来不是“怎么让图片掉下去”,而是图片异步加载和窗口 resize 的组合问题——两个事件触发时机不同、计算节奏不一致,列高数组极易错乱。多数人调试半天才发现,问题不在算法,而在没把 img.onload 和 resize 的状态同步起来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










