最直接的响应式网格列数控制是用 grid-template-columns 配合 @media:小屏单列(1fr),中屏双列(repeat(2, 1fr)),大屏三列(repeat(3, 1fr)),推荐 auto-fit + minmax() 和 rem 断点。

用 grid-template-columns 配合 @media 控制列数最直接
不需要 js,纯 css 就能根据屏幕宽度动态切换列数。核心是把 grid-template-columns 设为可变值(如 repeat(auto-fit, minmax(300px, 1fr)))),再用媒体查询覆盖特定断点下的列数。
- 小屏(手机):设为
1fr,强制单列 - 中屏(平板):用
repeat(2, 1fr) - 大屏(桌面):用
repeat(3, 1fr)或更多 - 避免用固定像素值做
minmax()下限,否则在窄屏可能撑破容器
auto-fit 和 auto-fill 的区别影响布局行为
两者都用于自动填充列,但触发时机不同:auto-fit 会合并空列,让内容占满整行;auto-fill 则保留所有生成的轨道,哪怕没内容。响应式场景下几乎总该选 auto-fit。
- 用
auto-fit:剩余空间会被已渲染项拉伸占用 - 用
auto-fill:可能出现大量空白列,尤其在小屏下 - 搭配
minmax(250px, 1fr)时,auto-fit能让三列变两列再变一列,过渡更自然
媒体查询断点别硬写像素值,优先用相对单位或设备特性
写死 @media (max-width: 768px) 容易和设计稿脱节。更稳妥的方式是基于内容容器宽度(比如父元素 max-width: 40rem)或使用 prefers-reduced-motion 等辅助功能检测作补充。
- 推荐用
em或rem:例如@media (max-width: 40rem),随根字体缩放 - 避免只靠宽度判断:加一句
and (hover: hover)可区分触屏/非触屏设备 - 如果项目已用 CSS 自定义属性,可以把断点存成
--breakpoint-md: 40rem,便于统一维护
.container { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)))); gap: 1rem; } @media (max-width: 40rem) { .container { grid-template-columns: 1fr; } } @media (min-width: 40.063rem) and (max-width: 64rem) { .container { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 64.063rem) { .container { grid-template-columns: repeat(3, 1fr); } }
实际调试时最容易被忽略的是 gap 在小屏下显得过大,以及没重置 grid-auto-rows 导致高度不一致。列数变化本身很简单,真正花时间的是微调间距、对齐和边界行为。