用 display: grid + minmax() + gap 即可实现主流设备自适应商品展示,无需媒体查询或框架;关键写法为 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)),配合 object-fit 控图、srcset/sizes 响应式加载及图片占位处理。

直接用 display: grid + minmax() + gap 就能搞定主流设备的自适应商品展示,不用写一堆媒体查询,也不用引入框架——除非你明确要兼容 IE11 或需要轮播、筛选等交互功能。
用 grid-template-columns: repeat(auto-fill, minmax()) 实现自动列数切换
这是现代响应式商品栅格最干净的写法。最小列宽设为 280px,容器够宽就多加一列,窄了就自动回退到单列:
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
关键点:
-
auto-fill确保空列也占位,避免最后一行卡片左对齐难看 -
minmax(280px, 1fr)表示“至少 280px,有空间就均分”,不是固定列数 -
gap比给每个.product加margin-bottom更可靠,不会触发 margin 合并 - 移动端小屏(如 iPhone SE)自然变成单列,平板大概率两列,桌面三列起,无需断点
图片高度不一致?用 object-fit + 固定容器高
商品图尺寸参差不齐时,卡片会高低错落,破坏网格感。别靠 JS 裁剪或后端统一尺寸,CSS 就能控住:
立即学习“前端免费学习笔记(深入)”;
.product img {
width: 100%;
height: 180px;
object-fit: cover;
}
注意:
- 必须同时设
width和height,否则object-fit不生效 -
object-fit: cover是裁剪居中,contain是等比缩放留白,按设计选 - 如果想保持宽高比且兼容老浏览器,得用伪元素撑开:
.product::before { padding-top: 133%; },再把图片设为position: absolute
响应式图片加载别只写 max-width: 100%
光靠 max-width 只解决“不溢出”,但高 DPR 屏(如 iPhone)会加载大图浪费带宽,小屏也可能拉伸模糊。真响应式得组合用:
-
srcset提供多个尺寸源:<img src="p-300.jpg" srcset="p-300.jpg 300w, p-600.jpg 600w, p-900.jpg 900w"> -
sizes告诉浏览器“这张图在不同断点下占多宽”:sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" - 漏写
sizes?浏览器默认按100vw算,大概率加载最大图 - 如果项目用 WebP,记得 fallback:
<picture><source type="image/webp" srcset="..."><img src="..."></picture>
要不要用 Bootstrap 或其他框架?
如果你只是静态产品展示页,没交互、无筛选、不需轮播,框架反而增加冗余 CSS 和学习成本。Bootstrap 的 .row/.col 在现代布局里是倒退——它本质还是 float/flex 模拟栅格,而原生 grid 更精准、更少 hack。
但以下情况建议用:
- 团队里有人不熟悉现代 CSS,或项目要快速交付+后续交由非技术人员维护
- 必须兼容 IE11(此时 grid 的
auto-fill/minmax不支持,得降级到flex-wrap+flex-basis) - 已有轮播、模态框、表单验证等配套需求,重复造轮子不如复用
真正容易被忽略的是图片占位:异步加载时 <img> 高度为 0,卡片突然塌陷,用户正在滚动就会“跳一下”。这不是 JS 能优雅解决的,得从 HTML 结构提前预留空间——要么写死 height,要么用 aspect-ratio(Chrome 103+),要么用伪元素撑开。没处理这点,再漂亮的 grid 布局也会在真实网络环境下露馅。



















