如何用CSS Grid实现可横向滚动的24列重复网格布局?
问题
想用24列CSS Grid布局展示产品,要求网格排满后横向溢出页面并支持滚动,同时产品卡片要和页面其他网格对齐。已经用百分比方式实现了该布局,但尝试用CSS Grid复现时,新增的项目会被挤压到剩余空间里。目前想到的办法是把每3个项目包在独立div里当单独网格,但想找更好的实现方式。
解决方案
无需额外包裹元素,通过调整Grid容器的宽度规则和自动轨道配置,就能实现横向滚动的24列对齐布局。
核心修改(宽屏媒体查询部分)
@media only screen and (min-width: 800px) { .grid { display: grid; grid-auto-flow: column; column-gap: 16px; /* 让容器宽度由内容撑开,超出屏幕时触发横向滚动 */ width: fit-content; overflow-x: auto; /* 保留滚动对齐样式,和移动端体验统一 */ margin: 0 -32px; padding: 0 32px; scroll-padding-left: 32px; scroll-snap-type: x mandatory; /* 定义基础24列网格 */ grid-template-columns: repeat(24, 1fr); /* 自动生成等宽的24列单元,避免项目挤压 */ grid-auto-columns: minmax(0, 24fr); } .grid__item { width: auto; scroll-snap-align: start; } /* 修正项目的网格列定位,适配24列系统 */ .grid__item:nth-child(4n-7) { grid-column: 2 / span 6; } .grid__item:nth-child(4n-6) { grid-column: 9 / span 8; } .grid__item:nth-child(4n-5) { grid-column: 18 / span 5; } .grid__item:nth-child(4n-4) { grid-column: 24 / span 7; } }
关键原理
width: fit-content:取消Grid容器的100%宽度限制,让容器宽度由内部网格内容决定,超出屏幕时自然横向滚动。grid-auto-columns: minmax(0, 24fr):当现有24列轨道不够时,自动生成新的等宽24列单元,确保每组产品都在完整的24列网格中布局,不会被挤压。- 保留
scroll-snap样式:维持和移动端一致的滚动对齐体验,滚动时产品卡片自动对齐屏幕边缘。
完整可运行代码
CSS
/* Base */ body { box-sizing: border-box; font-family: Arial, sans-serif; margin: 0; padding: 32px; width: 100%; } img { display: block; margin: 0 0 16px; width: 100%; max-width: 100%; } h3 { border-bottom: 1px solid black; font-size: 14px; margin: 0 0 8px; padding: 0 0 8px; } p { font-size: 12px; margin: 0; padding: 0; } /* Mobile Grid */ .grid { display: flex; flex-wrap: nowrap; column-gap: 16px; margin: 0 -32px; overflow-x: auto; padding: 0 32px; scroll-padding-left: 32px; scroll-snap-type: x mandatory; } .grid__item { box-sizing: border-box; display: flex; flex-shrink: 0; flex-direction: column; margin-bottom: 32px; padding: 0; position: relative; scroll-snap-align: start; width: 100%; max-width: 100%; } /* Tablet */ @media only screen and (min-width: 600px) { .grid__item { width: calc(50% - (16px / 2)); } } /* Wide */ @media only screen and (min-width: 800px) { .grid { display: grid; grid-auto-flow: column; column-gap: 16px; width: fit-content; overflow-x: auto; margin: 0 -32px; padding: 0 32px; scroll-padding-left: 32px; scroll-snap-type: x mandatory; grid-template-columns: repeat(24, 1fr); grid-auto-columns: minmax(0, 24fr); } .grid__item { width: auto; scroll-snap-align: start; } .grid__item:nth-child(4n-7) { grid-column: 2 / span 6; } .grid__item:nth-child(4n-6) { grid-column: 9 / span 8; } .grid__item:nth-child(4n-5) { grid-column: 18 / span 5; } .grid__item:nth-child(4n-4) { grid-column: 24 / span 7; } }
HTML
<div class="grid"> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>Product Title</h3> <p>Lorem ipsum dolor sit amet</p> </div> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>Product Title</h3> <p>Lorem ipsum dolor sit amet</p> </div> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>Product Title</h3> <p>Lorem ipsum dolor sit amet</p> </div> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>Product Title</h3> <p>Lorem ipsum dolor sit amet</p> </div> <!-- 新增测试项目 --> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>New Product</h3> <p>New product content</p> </div> <div class="grid__item"> <img src="https://images.pexels.com/photos/15031202/pexels-photo-15031202/free-photo-of-canoe-on-lake-in-mountains.jpeg"> <h3>New Product 2</h3> <p>Another new product</p> </div> </div>
内容的提问来源于stack exchange,提问作者user1406440
相关产品推荐
相关产品推荐

