CSS Grid横向滚动布局如何用方形div填充网格空白
场景背景
在设置为水平溢出滚动的容器中渲染约80个div元素,元素分为两类:纯色方形div、包含<p>标签的文本div。由于文本内容长短不一,无法预先指定元素在网格中的跨列宽度;同时文本元素通过JavaScript动态生成插入,位置无法提前确定。
问题描述
当前网格列会被文本长度拉伸,空白位置未被方形div填充,需要实现方形div自动填充网格所有空白区域。
CSS类名约定:包含文本的div类名为
.textbox,纯色方形div类名为.box
效果对比
- 当前实现效果:

- 期望实现效果:

现有代码
CSS代码
.containerMed { width: 1500px; position: relative; overflow-y: hidden; overflow-x: scroll; display: grid; gap: 5px; padding: 2.5px; grid-template-rows: repeat(7, 1fr); grid-auto-flow: column dense; } .box{ width: 30px; height: 30px; border-radius: 3px; grid-row-end: span 1; grid-row-end: span 1; } .textbox { font-size: 33px; white-space: nowrap; line-height: 0.8; }
JSX代码
function GridPattern(props) { let lineup = ["Oneohtrix Point Never", "Kilo Kish", "Sudan Archives","L'Rain"," Weyes Blood","Pussy Riot", "Serpentwithfeet","Jacques Greene","Envelop", "Telefon Tel Aviv","Julianna Barwick"] let n = Array.from(Array(80).keys()) const boxes = n.map((num) => { if (num % 9 === 0) return <div key={num} className="textbox" style={{ color: props.color }}> <p>{lineup[num % 12]}</p></div> else return <div key={num} className={props.pattern} style={{ backgroundColor: props.color }}></div> }) return boxes } function App() { <div className="containerMed" style={{ backgroundColor: 'green', height: '250px'}}> <GridPattern pattern="box" color='blue'></GridPattern> </div> }
解决方案
问题出在没有为Grid定义固定的基础单元格尺寸,默认的auto列宽会被长文本拉伸,导致列宽和30px的方形box不匹配,出现错位留空。按以下修改即可:
- 为网格容器固定基础单元格尺寸:添加
grid-auto-columns: 30px让所有自动生成的列宽固定为30px(和box宽度一致),同时把grid-template-rows的1fr改为固定30px,让行高也和box高度匹配,保证基础单元格是30px*30px的正方形。 - 精简
.box样式:删除重复写了两次的grid-row-end: span 1,去掉写死的width、height属性,让box自动填满单个基础单元格即可,避免尺寸和网格单元格错位。 - 调整
.textbox样式:添加grid-row: span 1强制文本框只占1行高度,避免大字号文本撑高网格行;同时重置文本框内<p>标签的默认margin,避免额外边距撑乱布局。
你已经开启了grid-auto-flow: column dense,dense排列算法会自动把后续的单格box填充到文本块旁留下的零散空位,不需要额外写JS计算位置。
另外你的JSX代码里App组件缺少return语法,属于语法错误,记得补上。
修改后的完整CSS代码:
.containerMed { width: 1500px; position: relative; overflow-y: hidden; overflow-x: scroll; display: grid; gap: 5px; padding: 2.5px; /* 固定7行,每行高度30px,匹配box尺寸 */ grid-template-rows: repeat(7, 30px); /* 自动生成的列宽度固定30px,匹配box尺寸 */ grid-auto-columns: 30px; /* dense模式开启自动回填空位 */ grid-auto-flow: column dense; } .box{ border-radius: 3px; /* 宽高由网格单元格决定,刚好占满30*30的格子 */ } .textbox { font-size: 33px; white-space: nowrap; line-height: 0.8; /* 强制文本块只占1行高度 */ grid-row: span 1; } /* 清除p标签默认外边距 */ .textbox p { margin: 0; }
修正后的JSX代码(补全return语法):
function GridPattern(props) { let lineup = ["Oneohtrix Point Never", "Kilo Kish", "Sudan Archives","L'Rain"," Weyes Blood","Pussy Riot", "Serpentwithfeet","Jacques Greene","Envelop", "Telefon Tel Aviv","Julianna Barwick"] let n = Array.from(Array(80).keys()) const boxes = n.map((num) => { if (num % 9 === 0) return <div key={num} className="textbox" style={{ color: props.color }}> <p>{lineup[num % 12]}</p></div> else return <div key={num} className={props.pattern} style={{ backgroundColor: props.color }}></div> }) return boxes } function App() { // 补全缺失的return return ( <div className="containerMed" style={{ backgroundColor: 'green', height: '250px'}}> <GridPattern pattern="box" color='blue'></GridPattern> </div> ) }
内容的提问来源于stack exchange,提问作者Laiqa Mohid
相关产品推荐
相关产品推荐

