让2048棋盘适应窄屏:Grid、宽高比与长数字的排版边界

举报
yd_251117598 发表于 2026/11/02 20:22:41 2026/11/02
【摘要】 用独立的CSS教学示例拆解2048窄屏布局:让棋盘跟随父容器,统一盒模型与间距,使用四列Grid和自动高度保持方形,并区分长数字适配、页面缩放与真实设备验收。

昨天讨论了2048满盘时的结束判定。这一篇换到界面层:桌面看着规整的4×4棋盘,为什么到了窄屏会出现横向滚动、格子被撑宽,或者四位数字挤出方块?

本文给出独立的布局教学示例,不修改此前部署的游戏,也不声称已做真机兼容测试。重点是把容器尺寸、网格轨道和数字内容分开处理,让问题可以逐层定位。

一、先让棋盘跟随父容器

固定写width:500px,再在手机上加一个transform:scale(…),常常只是把视觉内容缩小。元素原本占据的布局空间仍可能存在,周围的按钮、说明文字与点击区域也不容易同步。更直接的方式是让棋盘宽度由父容器约束,上限只负责限制桌面尺寸。

<meta name="viewport" content="width=device-width, initial-scale=1">
<main class="game">
  <h1>2048</h1>
  <p>相同数字合并,继续挑战更高分。</p>
  <div class="board">
    <div class="tile">2</div><div class="tile">4</div>
    <div class="tile">8</div><div class="tile">16</div>
    <div class="tile">32</div><div class="tile">64</div>
    <div class="tile">128</div><div class="tile">256</div>
    <div class="tile">512</div><div class="tile">1024</div>
    <div class="tile">2048</div><div class="tile">4096</div>
    <div class="tile">8192</div><div class="tile">16384</div>
    <div class="tile tile--long">32768</div>
    <div class="tile tile--long">65536</div>
  </div>
</main>

这里有16个静态格子,只用于观察排版,不含移动、分数或随机生成逻辑。viewport设置也不禁止用户缩放;不要为了让棋盘“看起来不乱”,加入user-scalable=no来牺牲可读性。

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; }
.game { width: min(100%, 32rem); margin-inline: auto; }
.board {
  --space: clamp(0.35rem, 1.5vw, 0.75rem);
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(4, minmax(0, 1fr));
  gap: var(--space);
  padding: var(--space);
  border-radius: 0.75rem;
  background: #b9aca0;
}
.tile {
  min-width: 0;
  min-height: 0;
  display: grid;
  place-items: center;
  border-radius: 0.4rem;
  background: #eee4da;
  color: #51483f;
  font: 700 clamp(1rem, 5vw, 2.5rem) / 1.1 system-ui, sans-serif;
  white-space: nowrap;
}
.tile--long { font-size: clamp(0.8rem, 3.5vw, 1.75rem); }

width:100%参照的是父容器,不是整个屏幕。body的内边距先留出两侧空间,game再取得剩余宽度,桌面时最多32rem。统一border-box后,board的内边距包含在其声明宽度内,不会在100%之外再额外增加一圈宽度。

二、正方形不是同时写死宽和高

MDN对aspect-ratio的说明强调,至少一个尺寸需要自动计算,宽高比才会参与尺寸推导。这里宽度由父容器决定,高度保留auto,期望比例为1:1。不要再叠加height:500px,否则窄屏时会得到又窄又高的棋盘。

aspect-ratio表达的是首选比例,不是任何内容条件下都必须维持的硬约束。最小尺寸、最大尺寸、内容贡献以及其他布局规则都可能影响最终结果。排查时应查看实际盒尺寸,而不是仅看到CSS里有1/1就认定页面一定是正方形。

示例明确指定四行四列,格子数量保持16个。增加提示文字、失败遮罩或动画层时,不要把它们作为第17个普通网格子项塞进同一层;可以放到棋盘外,或设计独立的覆盖层。

三、四列1fr仍可能被内容顶开

仅写repeat(4,1fr),并不总等于“每列无条件占四分之一”。网格轨道存在自动最小尺寸,长内容可能影响最小宽度。这里用minmax(0,1fr)明确允许轨道缩小,同时在tile上设置min-width:0。

但允许轨道缩小,不等于文字自动变小。布局系统和字体适配是两件事:即使格子已经正确均分,65536仍可能比2需要更多空间。因此示例给长数字单独的字体规则。实际游戏应由渲染层按数字位数选择样式,不让排版类参与合并算法。

例如,五位以上数字可以使用tile–long。这个阈值只是示例策略,字体、可用宽度和支持的最大数字都会影响最终选择。若允许无限继续挑战,就不能承诺一套固定字号适配任意长度;需要为更多位数制定进一步的显示策略并验证。

不要用text-overflow:ellipsis把32768变成327…,也不要直接overflow:hidden把关键数字裁掉。数字是游戏状态的一部分,隐藏它会让布局看似整齐,却让玩家无法正确判断。

四、间距需要一起进入尺寸计算

把棋盘的实际边长记作B,内边距为p,列间距为g;本例没有边框,那么每个格子的可用边长可以写成:

cell = (B - 2p - 3g) / 4

四列之间只有三条间隔,外侧空白由padding提供。若B为320px、p和g都为8px,则cell为70px。这是根据假设尺寸计算的示例,不是真机测量结果。

窄屏下若坚持很大的固定间距,数字真正得到的空间会越来越少。clamp让间距有上下限,并在中间随视口变化。也要记住,vw参照视口;如果棋盘被放进桌面侧栏,视口很宽而父容器很窄,间距仍可能达到上限。遇到这种嵌入场景,可以改用更小的固定间距或容器查询,不能把全屏页面的参数直接当成通用组件参数。

五、验收要包含内容和缩放

下面是建议执行的接入检查,本篇没有把这些检查冒称为已经通过的测试:

  1. 在320、375、768像素等不同宽度下查看页面,确认没有意外横向滚动,棋盘四列四行完整。
  2. 同时放入一位、四位、五位及产品允许的最长数字,检查是否完整可读;只用2做演示无法覆盖问题。
  3. 增大浏览器缩放和默认字体,确认按钮、标题和说明仍可阅读,必要时允许页面纵向滚动。
  4. 在横屏低高度窗口检查上下内容。优先保留正常滚动,不为一屏放下所有内容把按钮缩得过小。
  5. 若真实游戏采用绝对定位的棋子动画层,检查它和背景格使用同一套padding、gap与尺寸来源,避免静态格正确而动画落点偏移。

这个静态示例没有处理触摸手势、键盘焦点、动画、屏幕阅读器播报或完整的颜色对比度审计。响应式布局做对,只说明尺寸约束更清楚,不能代替交互和无障碍验收。

参考:MDN《aspect-ratio》:https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/aspect-ratio。该资料用于核对首选宽高比和自动尺寸的语义;棋盘示例及尺寸推导为本文独立整理。

写作说明:本文由AI辅助整理与撰写,代码为独立教学示例,不涉及本机文件上传,也未修改线上项目。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。