bootstrap栅格因flex/float线性布局导致图片切片留白错位,masonry需移除col-*类、用.grid-sizer控制列宽、imagesloaded确保图片加载完成、resize时destroy再reinit以适配响应式。

为什么直接用 Bootstrap 栅格做图片切片会留白、错位
因为 .row + .col-* 是 flex 或 float 线性布局,每行高度取最高项,下方行从新起点开始——不同高度的图片放进去,必然出现垂直缝隙,根本不是“切片”而是“硬切行”。Masonry 要的是按列逐个填空,逻辑上就和 Bootstrap 栅格冲突。
必须移除所有 col-* 类,改用 Masonry 控制列宽
常见错误是把 .item 套在 .col-md-4 里面,结果 Masonry 读不到真实宽度,定位全乱。正确做法是:
- 容器只保留
.masonry(别加.row) - 每个图片卡片外层加
.item,且直接去掉所有col-* - 列宽交给 Masonry:加一个隐藏的
.grid-sizer元素,CSS 设为width: calc(33.333% - 1rem)(对应三列) - 初始化时传
columnWidth: ".grid-sizer"和percentPosition: true
imagesLoaded 不是可选,是 Masonry 正常工作的前提
图片没加载完就调用 masonry(),offsetHeight 读出来是 0,所有卡片堆叠在一起——这不是 bug,是必然行为。典型报错:Cannot read property 'offsetTop' of undefined。
必须这样写:
$('.masonry').imagesLoaded().done(function() {
$('.masonry').masonry({
itemSelector: '.item',
columnWidth: '.grid-sizer',
percentPosition: true
});
});
如果用了懒加载 data-src 或 <picture></picture>,得手动触发 imagesLoaded 或用伪元素 hack 补充检测。
响应式列数切换不能只靠 CSS,要 destroy + reinit
Masonry 不监听 resize,窗口变窄后还卡在三列,卡片挤成一团。不能只改 .grid-sizer 宽度,必须手动重建实例:
- 监听
window.addEventListener('resize'),但加防抖(比如 150ms)避免频繁触发 - 用
getComputedStyle读当前容器宽度,对照 Bootstrap 断点(576px、768px、992px)决定列数 - 先调
instance.destroy(),再用新columnWidth和gutter重新new Masonry() -
.grid-sizer的宽度必须同步更新(比如小屏设为width: 100%)
最易被忽略的是:列数变化时,旧实例残留会导致位置计算错乱,不 destroy 就重 init,大概率出视觉重叠。











