使用CSS Grid实现棋盘游戏的均匀分布正方形单元格
解决CSS Grid棋盘UI的自适应与比例问题
问题描述
我尝试用CSS Grid创建简单棋盘游戏UI,原本以为这是理想工具,但无法实现以下预期效果:
- 单元格自动调整尺寸填充父容器
- 单元格保持1:1宽高比
- 页面内容不超出浏览器可视窗口范围
试过的方案要么导致内容溢出,要么单元格过高时页面横向扩展,或单元格过宽时页面纵向扩展。
原代码示例
CSS
:root { --col_and_row_count: 10; } .main { display: grid; grid-template-rows: 60px 1fr 60px; gap: 1em; height: 100vh; } .wrapper { display: grid; grid-template-columns: 200px 1fr; } .board { display: flex; align-items: center; } .tiles { margin: auto; display: grid; grid-template-columns: repeat(var(--col_and_row_count), 1fr); gap: 12px; aspect-ratio: 1; } .tiles > div { background: green; }
HTML
<div class="main"> <div> Some heading text goes here </div> <div class="wrapper"> <div> The side bar goes here </div> <div class="board"> <div class="tiles"> <div data-tile-index="0"></div> <div data-tile-index="1"></div> <div data-tile-index="2"></div> <div data-tile-index="3"></div> <div data-tile-index="4"></div> <div data-tile-index="5"></div> <div data-tile-index="6"></div> <div data-tile-index="7"></div> <div data-tile-index="8"></div> <div data-tile-index="9"></div> <div data-tile-index="10"></div> <div data-tile-index="11"></div> <div data-tile-index="12"></div> <div data-tile-index="13"></div> <div data-tile-index="14"></div> <div data-tile-index="15"></div> <div data-tile-index="16"></div> <div data-tile-index="17"></div> <div data-tile-index="18"></div> <div data-tile-index="19"></div> <div data-tile-index="20"></div> <div data-tile-index="21"></div> <div data-tile-index="22"></div> <div data-tile-index="23"></div> <div data-tile-index="24"></div> <div data-tile-index="25"></div> <div data-tile-index="26"></div> <div data-tile-index="27"></div> <div data-tile-index="28"></div> <div data-tile-index="29"></div> <div data-tile-index="30"></div> <div data-tile-index="31"></div> <div data-tile-index="32"></div> <div data-tile-index="33"></div> <div data-tile-index="34"></div> <div data-tile-index="35"></div> <div data-tile-index="36"></div> <div data-tile-index="37"></div> <div data-tile-index="38"></div> <div data-tile-index="39"></div> <div data-tile-index="40"></div> <div data-tile-index="41"></div> <div data-tile-index="42"></div> <div data-tile-index="43"></div> <div data-tile-index="44"></div> <div data-tile-index="45"></div> <div data-tile-index="46"></div> <div data-tile-index="47"></div> <div data-tile-index="48"></div> <div data-tile-index="49"></div> <div data-tile-index="50"></div> <div data-tile-index="51"></div> <div data-tile-index="52"></div> <div data-tile-index="53"></div> <div data-tile-index="54"></div> <div data-tile-index="55"></div> <div data-tile-index="56"></div> <div data-tile-index="57"></div> <div data-tile-index="58"></div> <div data-tile-index="59"></div> <div data-tile-index="60"></div> <div data-tile-index="61"></div> <div data-tile-index="62"></div> <div data-tile-index="63"></div> <div data-tile-index="64"></div> <div data-tile-index="65"></div> <div data-tile-index="66"></div> <div data-tile-index="67"></div> <div data-tile-index="68"></div> <div data-tile-index="69"></div> <div data-tile-index="70"></div> <div data-tile-index="71"></div> <div data-tile-index="72"></div> <div data-tile-index="73"></div> <div data-tile-index="74"></div> <div data-tile-index="75"></div> <div data-tile-index="76"></div> <div data-tile-index="77"></div> <div data-tile-index="78"></div> <div data-tile-index="79"></div> <div data-tile-index="80"></div> <div data-tile-index="81"></div> <div data-tile-index="82"></div> <div data-tile-index="83"></div> <div data-tile-index="84"></div> <div data-tile-index="85"></div> <div data-tile-index="86"></div> <div data-tile-index="87"></div> <div data-tile-index="88"></div> <div data-tile-index="89"></div> <div data-tile-index="90"></div> <div data-tile-index="91"></div> <div data-tile-index="92"></div> <div data-tile-index="93"></div> <div data-tile-index="94"></div> <div data-tile-index="95"></div> <div data-tile-index="96"></div> <div data-tile-index="97"></div> <div data-tile-index="98"></div> <div data-tile-index="99"></div> </div> </div> </div> <div> This is the footer </div> </div>
解决方案
调整CSS代码,解决溢出、比例和自适应问题:
修改后的CSS
:root { --col_and_row_count: 10; --tile-gap: 12px; } * { margin: 0; padding: 0; box-sizing: border-box; } .main { display: grid; grid-template-rows: 60px 1fr 60px; gap: 1em; height: 100vh; overflow: hidden; /* 阻止整体内容超出视口 */ } .wrapper { display: grid; grid-template-columns: 200px 1fr; gap: 1em; /* 避免侧边栏与棋盘容器挤压 */ } .board { display: flex; align-items: center; justify-content: center; padding: 1em; /* 防止棋盘贴边 */ overflow: hidden; /* 限制棋盘在容器内 */ } .tiles { display: grid; grid-template-columns: repeat(var(--col_and_row_count), 1fr); gap: var(--tile-gap); width: 100%; max-width: 100%; max-height: 100%; aspect-ratio: 1; /* 保持棋盘整体正方形比例 */ } .tiles > div { background: green; aspect-ratio: 1; /* 强制每个单元格1:1比例 */ }
关键修改说明
- 全局盒模型重置:
*选择器设置box-sizing: border-box,确保内边距、边框不会额外增加元素尺寸,从根源避免溢出。 - 限制整体视口范围:给
.main加overflow: hidden,确保页面内容不会超出浏览器可视窗口。 - 优化棋盘容器布局:
.board添加justify-content: center让棋盘水平居中,padding防止棋盘贴边,overflow: hidden限制棋盘不会超出容器。 - 棋盘自适应与比例控制:
.tiles设置width: 100%和max-width/max-height: 100%,让它填充父容器但不超出;保留aspect-ratio:1确保棋盘始终是正方形。 - 单元格比例锁定:给每个单元格设置
aspect-ratio:1,强制保持1:1宽高比,无论父容器尺寸如何变化都不会变形。
调整后即可实现:单元格自动填充父容器、保持1:1比例、页面内容完全在可视窗口内的效果。
内容的提问来源于stack exchange,提问作者LairdPleng
相关产品推荐
相关产品推荐

