做Vibe Coding大半年,陆陆续续写了不少小项目,最让我上瘾的其实是游戏页面开发。原因很简单:游戏界面的反馈是即时的,布局一改、颜色一换,立刻就能看到效果,特别适合用来验证Vibe Coding那套“描述需求—生成代码—审查迭代”的工作流。这篇是第九篇笔记,主题锁定在“开发游戏页面”里的第一个硬骨头:界面布局。
为什么要单独把布局拎出来写一篇?因为游戏页面和其他类型的网页(比如官网、后台管理系统)很不一样。它不是一个从上往下读的文档流,而是一块“空间”——地图在中间,信息在顶部,按钮在底部,每一块区域都要精确地占据屏幕。用Vibe Coding做这种布局,最大的优势是你不需要从零手写那些CSS长篇,而是把设计意图说清楚,让AI先把骨架搭出来,你再基于实际效果去调。这篇文章我会把完整过程、踩过的坑、以及怎么用对话控制AI生成正确布局的套路梳理一遍,给同样在折腾Vibe Coding的人一份可复用的作业。
1. 为什么游戏页面布局适合做Vibe Coding练手
1.1 游戏UI天然是“结构驱动”的
做网站的时候,大多数人的习惯是边写边想,一个section一个section堆下来,最后发现问题再回头改。游戏页面不一样,它的结构非常明确:顶部状态栏、中间游戏区、底部操作区。这种清晰的三段式结构,恰恰是自然语言最容易描述、AI最容易理解的东西。
我试过几次之后发现,你对AI说“我想做一个竖屏小游戏页面,顶部显示分数和生命值,中间是地图网格,底部放方向控制按钮”,它几乎能一步到位生成一个可用的框架。原因其实不玄乎——游戏UI的结构模型已经被收录得非常充分了,主流代码生成模型对“顶部、中间、底部”这种布局语义的把握非常稳。
但这里有个前提:我们自己心里得有那个结构图。Vibe Coding不是让你当甩手掌柜,而是让你把脑子里的架构“翻译”成人话。结构想清楚了,AI才知道该怎么排;结构模糊,AI就会自己脑补,出来的东西大概率不是你要的。
1.2 布局迭代的天然闭环
游戏页面有一种奇妙的特性:它的正确性可以“看”出来。你不需要跑复杂的单元测试,只需要在浏览器里打开页面,一眼就能看出按钮是不是偏了、地图有没有溢出、顶栏是不是太低。这种即时视觉反馈,让“生成—验证—修改”的循环变得非常快。
Vibe Coding的核心循环本来就是:提出需求 → 生成代码 → 运行验证 → 发现问题 → 继续修改。游戏页面是这个循环最完美的载体。我之前用传统方式调一个响应式布局,可能要来回刷新二十多次;用Vibe Coding之后,通常三轮以内就能达到“能玩”的水平。
我个人觉得这就是Vibe Coding在游戏UI领域最舒服的地方——它不像业务系统那样需要严格的数据流约束,也不需要精准的类型定义,纯视觉、纯布局的任务恰好是生成模型的强项。
1.3 一次明确的小目标
作为第九篇笔记,我给这个练习定了一个特别具体的目标:做一个像素风小游戏的页面,不涉及复杂的游戏逻辑,只做静态界面。具体来说是三块:顶部信息栏(生命值、分数、关卡)、中部游戏地图(网格棋盘)、底部控制区(方向键和互动按钮)。
这个目标的难度刚好卡在“新手能上手、老手也有收获”的位置。对于刚接触Vibe Coding的读者来说,你不需要懂什么复杂算法,就能看到AI怎么理解你的意图;对于已经写了几个项目的读者,这一篇的对话思路和审查方法也可以直接迁移到更大体量的项目里。说白了,这是一个标准的“学一次、用一辈子”的布局模版。
2. 需求描述:怎么把布局意图“喂”给AI
2.1 说人话:先写一段“看的懂”的布局描述
Vibe Coding最核心的能力,是你描述得越具体,生成结果越贴合需求。但“具体”不是说你把每个px都写上,而是要把布局关系讲清楚。
我的做法是先在文本编辑器里写一段“伪需求”,像这样:
页面整体竖屏,移动端优先,宽度适配375px。顶部栏高60px,背景深色半透明,左边显示生命值图标+数值,右边显示分数。中间区域占满剩余高度,内部是一个棋盘格地图,格子数量6行8列。底部区域高180px,左半边放十字方向键,右半边放跳跃/攻击两个按钮。
这段描述看起来挺长,但每一句话对应一个布局决策。AI拿到这段文字之后,会自己拆解成HTML结构和CSS样式——顶部栏是flex布局,中间是grid,底部是flex+grid的嵌套组合。你不需要告诉它用什么布局方式,只要它读得懂这种空间关系,方案就出来了。
我一开始也犯过“过度指定”的错误,比如写“用display:flex和justify-content:space-between”,结果AI把那些我自作聪明的属性全部用上,反而让代码变丑。真正好用的描述方式是“给意图,不给实现”。
2.2 上下文分块:一次只聊一个区域
Vibe Coding踩坑最多的地方,就是一口气把所有需求全部丢给模型,期望它一次性给你一个完美页面。实际结果通常是:大方向没错,细节一塌糊涂——按钮文字挤在一起、地图格子比例不对、顶部栏间距错乱。
我的经验是把布局目标拆成三个子任务,逐块对接:
- 先做顶部状态栏的布局;
- 再做中间地图的网格结构;
- 最后做底部控制区的排列。
每个子任务都是一轮独立的对话。比如中间地图那块,我会说“帮我做一个8行6列的网格,每个格子是正方形,格子之间有1像素的缝隙,背景要有棋盘格纹理”。然后单独看这段代码是否正常,确认之后再告诉AI“继续,接下来做底部的控制按钮”。
这种分块迭代的方式,对抗AI翻车的能力特别强。因为每一次变更都建立在一个已经验证过的基点之上,出了问题只需要回滚到上一个正确的步骤,不需要重新折腾整个页面。
2.3 让AI自己解释布局方案
有一个我最近越来越爱用的技巧:在让AI写代码之前,先让它给我描述一遍布局方案。比如我会问“你打算怎么排这个底部控制区?用grid还是flex?为什么?”它给出的解释里带着结构思考,我可以提前判断这个方案合不合理,而不是等代码写完了再来猜它的思路。
这样做有两个好处。第一,省改代码的时间。如果它说“底部用flex row排列”,但我想要的是“左方向区、右动作区”,那我就会立刻纠正,而不是等代码生成后才发现结构不对。第二,它真的会给你一些你没想到的方案。比如我问过一次“地图格子在窄屏上该怎么处理”,它建议用aspect-ratio保持宽高比,同时用minmax函数做自适应列宽——这个组合我手动写的时候经常漏掉,但AI却记得把两者放在一起。
Vibe Coding不是单向执行指令,而是一种“对话式设计”。
3. 核心布局实现:地图区、控制区、信息区
3.1 页面骨架:三段式结构到底怎么写
游戏页面的整体结构,我用一个最简单的父容器把所有内容串起来。父容器设置display: flex、flex-direction: column,高度占满视口(height: 100vh),再设置overflow: hidden禁止页面滚动。然后三个子区域从上到下排列:顶栏固定高度,中间区域flex: 1占满剩余空间,底部固定高度。
这个方案是游戏UI的经典做法,没有之一。原因很简单:游戏需要的是“满屏”的沉浸感,如果页面可以滚动,玩家会不小心触发浏览器手势,干扰操作。所以最外层必须钉死,中间区域自适应,上下两个区域固定。
代码上,我会要求AI生成一段带注释的HTML/CSS,关键结构类似下面这样:
<div class="game-wrapper"> <header class="top-bar">...</header> <main class="game-area">...</main> <footer class="control-area">...</footer> </div>.game-wrapper { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; } .top-bar { height: 60px; flex-shrink: 0; } .game-area { flex: 1; min-height: 0; } .control-area { height: 180px; flex-shrink: 0; }注意这里我特意加了height: 100dvh。这是移动端浏览器的一个经典坑:100vh在手机上会把地址栏的高度算进去,导致底部按钮被挡住。dvh是动态视口高度,会随地址栏显示/隐藏而变化。你不需要理解太深,只要知道加上这一行能让手机上的显示正确很多就够了。把这句话原样丢给AI,它会理解你的意图。
3.2 地图网格:用Grid天然契合棋盘语义
游戏地图本质上是一张棋盘格,而CSS Grid就是专门为这种场景设计的。为什么不用flex?因为flex的“流式排列”适合从左到右排一排按钮或者一列列表,但棋盘需要同时控制行和列的数量,还要让格子宽度一致,这个时候grid的两维能力正好命中需求。
我会让AI生成一个地图容器,用display: grid加上两个关键参数:
.game-map { display: grid; grid-template-columns: repeat(6, 1fr); grid-auto-rows: 1fr; gap: 2px; }这里把列数写死为6列,“1fr”表示每列平分宽度。行高用grid-auto-rows: 1fr,是为了让每一行都能根据内容自动保持正方形比例。实际上如果地图容器的高度是可变的,更稳妥的写法是每个格子设置aspect-ratio: 1 / 1,配合grid-template-columns: repeat(6, 1fr),这样无论屏幕多宽多高,格子永远是正方形。
当时我在这里调了很久,因为地图区域的高度是flex:1算出来的,格子的实际尺寸不可预知。AI第一次生成的效果是纵向被拉伸成长方形,不是正方形。我补充了一句“每个格子必须是正方形,用aspect-ratio实现”,它就改对了。这就是Vibe Coding的微妙之处——你得给模型一个明确约束,它才知道问题出在哪。
3.3 控制按钮:方向键与动作键的排布
底部控制区看起来简单,实际上是最考验布局细节的地方。左半部分十字方向键,右半部分跳跃/攻击按钮,两者之间不能太挤,也不能离得太远,不然单手操作的时候大拇指会够不到。
我的方案是靠flex布局加固定比例分区。底部容器整体设为display: flex,左侧控制区占flex: 1.2,右侧动作区占flex: 0.8。为什么要用1.2和0.8?因为十字方向键是一个3x3的格子阵列,横向需要三个按钮的位置,而右边只有纵向排列的两个大按钮,排布密度不一样,所以左侧需要稍微宽一点。
方向键本身是九宫格结构:上、左、中、右、下一个十字。实现时可以让AI生成一个3x3的grid,中心留空或者放一个“交互”按钮。每个方向键的尺寸用相对单位控制,不要写死px——我习惯用min(60px, 18vw)这种写法,意思是按钮最大60px,但在窄屏上按视口宽度18%缩放。这样在375px的手机和1024px的平板上都能保持手感。
动作按钮更简单,两个大圆形按钮纵排,间距12px左右。这里有一个容易被忽略的细节:按钮之间的点击区域不能重叠。移动端上用户手指粗,误触率比鼠标高很多,所以我会额外要求AI给动作按钮外侧加上margin或者让按钮本身的min-width、min-height不低于48px——这是移动端交互的最小安全尺寸,低于这个值,误触概率直线上升。
3.4 信息面板:数据和视觉焦点的平衡
顶部信息栏通常是游戏界面的“门面”——玩家第一眼看到的就是它。但这个区域的布局反而最不该抢戏。原因很简单:信息栏是功能性的,不是观赏性的,它必须一目了然,不能有花哨的排版干扰玩家读取数据。
我的方案是左中右三段式:左边生命值,中间关卡,右边分数。三个区域用flex平分宽度,每个区块内部摆放一个图标和一个数字。为了保证数字变化时视觉稳,建议数字用等宽字体(比如font-variant-numeric: tabular-nums),这样几十秒内分数从999变成1000,数字本身的宽度不会跳动,UI看起来更稳定。
另外一个容易被忽略的问题是信息栏的背景。游戏地图可能是亮色像素风,如果信息栏也是全透明白色底,玩家就分不清前景和背景。我一般让AI给信息栏加一层半透明深色背景,加一点backdrop-filter: blur(4px),既保留游戏画面的通透感,又保证文字可读性。这个CSS属性在移动端现代浏览器上兼容性已经不错,可以放心用。
4. 三轮实操对话:从骨架到完整页面
4.1 第一轮对话:搭出整体骨架
我建议所有Vibe Coding项目都从“最小骨架”开始。跟我实际操作一下,打开你惯用的AI编程助手,输入下面这句话:
请帮我用HTML+CSS做一个竖屏游戏页面框架。整体是移动端优先,宽度按照375px设计。页面高度占满视口不滚动,顶部60px信息栏,中间自适应区域放游戏地图,底部180px控制区。先不要写具体内容,用占位div铺满结构就好。
这一句话的目标很明确:让AI先交出一个可信的骨架,不要纠结细节。生成之后你检查三件事——有没有100vh/100dvh设置、有没有flex:1的区域占满空间、有没有把body的margin清零。这三个都对的话,第二轮就可以开始了。
我在这轮最容易遇到的问题是AI默认把页面做成了网页版居中内容区,结果手机上左右有白边。处理办法是把“占满视口、宽度响应式”再强调一遍,一般第二次生成就会修正。
4.2 第二轮对话:往骨架里填充游戏区域
骨架稳定之后,第二轮往中间区域填地图。我会输入:
中间的游戏区域是一个地图网格,6列8行,每个格子必须是正方形,使用CSS Grid实现。格子之间用2px的gap分隔。每个格子内部填充一个背景色块,模拟地块。底部控制区放一个十字方向键和两个圆形动作按钮,方向键用3x3网格。
这一轮生成后通常已经非常接近成品了。我对这轮的要求只有一个:结构和样式分离。也就是说HTML里应该只有布局结构的div,CSS里负责尺寸和排列。如果AI把样式写成了内联style="width: 40px"这种,一定要马上指出来,让它改成类名+外部CSS。后面游戏逻辑开始接入时,内联样式会变成灾难——你没法统一控制,只能一个个改。
另一个值得盯紧的点是方向键的“十字”结构。AI容易把中心也生成一个按钮,但实际上十字方向键的中心应该是空的(除非你要做“按下即确认”的交互)。我通常会在提示里明确写出“中心不放按钮,只保留上、下、左、右四个方向,加一个中心空位占位”。
4.3 第三轮对话:视觉细节和像素风定制
骨架和图块都到位之后,最后一轮集中打磨视觉效果。这个时候我会提一个整体的审美要求:
整体风格改成像素复古风。配色用暗灰背景、亮绿色地块、明黄色按钮。所有按钮加圆角和深色边框,按钮按下时有内部阴影效果。顶部信息栏半透明深色底,文字用白色,生命值用红色小方块图标代替。字体使用等宽字体。
视觉定制是Vibe Coding最爽的环节,因为描述“感觉”这件事AI真的比人快。你说“像素风、暗色、亮黄按钮”,它瞬间就能把对应的色值、圆角、边框都配置好。不过这里有个人经验要分享:任何一个视觉属性都必须能定位到具体代码,否则就当场追问“对应的CSS变量和类名是什么?”。
我踩过一次坑是AI给了我一堆花哨的渐变、阴影、拟物按钮,但玩家要的是快速识别的功能按钮。后来我加了“减少装饰,扁平风格为主”的约束,终于回到正轨。记住:游戏UI的第一目标是信息清晰,不是漂亮。这一点无论Vibe Coding写得有多爽,都得守住。
4.4 生成之后:审查清单比跑通更重要
Vibe Coding有个常见迷思:AI生成了代码,跑通了就等于成功了。不全对,尤其是在游戏页面这类纯视觉的领域。代码“能运行”和代码“写得好”是两回事。我给自己立了一个审查清单,大概有四条:
- 布局单位有没有写死像素?除了最小安全尺寸,大部分尺寸应该用相对单位。
- 有没有遗漏移动端的禁用操作?比如
user-select: none防止长按选中文字,touch-action: manipulation消除双击缩放延迟。 - 地图格子的数量能不能通过数据动态生成?还是写死的静态HTML?如果是游戏,后期一定要能循环渲染。
- 有没有可访问性隐患?比如按钮有没有aria-label,地图格子是否可以用键盘聚焦。
审查的时候我一般会打开Chrome DevTools的设备模拟器,切到375px宽度看一遍,再切到768px看一遍,最后在真实的手机上跑一次移动预览。每次都能揪出一两个AI埋下的暗雷——最常见的是底部按钮超出屏幕或者中间区域被压缩到看不见。
这一步看似繁琐,但恰恰是Vibe Coding和纯AI生成的分水岭。AI自动生成代码是技术,审查代码、发现问题、提出修正要求,才是工程能力。两者的区别就是会用搜索引擎和会做研究之间的区别。
5. 常见问题与排查技巧实录
5.1 “明明让它写6列,为什么只有5列?”
这个坑我遇到不下五次。AI生成的地图容器,明明设了grid-template-columns: repeat(6, 1fr),但实际渲染出来却只有5列或自动换行。原因通常是容器内实际有内容的子元素数量不是6的整数倍,或者某个子元素自身设置了display: block以外的影响布局的属性。
排查顺序是:先看HTML里到底生成了几个格子div,再看是不是有子元素被意外折叠(比如变成display: none),最后检查grid容器的宽度是不是被某个max-width限制了。绝大多数情况下都是最后一个原因——容器宽度不够,6列自然会被压缩到4、5列。解决方式是删除上层的max-width,或者把1fr改成minmax(0, 1fr),防止内容撑破格子的最小宽度。
5.2 “它把样式写进了JS里,我差点没发现”
Vibe Coding生成复杂页面时,有一种隐蔽的翻车方式:一部分HTML和CSS很干净,但某个交互逻辑用了JS直接改style。比如AI可能生成了一段mapCells.forEach(cell => cell.style.width = '50px')——你当时没注意,后面改了CSS就全乱套。
我的排查技巧是全局搜索style.和style=,一旦发现就要求AI把样式逻辑抽出来。游戏页面布局的规矩应该是:结构在HTML、样式在CSS、行为在JS,三者各自独立。如果AI把这三层混在一起,生成内容越多越难维护。
5.3 “地图区在手机上挤成一团”
这种情况多半是中间区域没有设置min-height: 0。flex布局里,子项的默认最小高度是内容高度,如果地图网格的格子内容很多,中间的flex:1区域会被内容撑开,然后挤出底部的控制区。
修复很简单:给.game-area加上min-height: 0,给控制区固定height并设置flex-shrink: 0。这属于CSS经典的“flex最小尺寸问题”,Vibe Coding生成时经常漏掉,所以我在审查清单里加了一条“flex子项是否有min-height: 0或overflow: hidden”。加上之后,几乎所有拉伸挤压问题都一劳永逸了。
5.4 “预览正常,真机一打开就错位”
预览器正常但真机不对,90%的概率是浏览器兼容性问题。我用过的最典型的案例是gap属性在部分旧版浏览器上不支持grid布局,导致格子之间没有间距。另一个就是之前提到的100vh和100dvh的差异。
这种问题靠对话去让AI排查效率很低,因为模型看不到真机效果。我的建议是优先掌握几个高价值属性的兼容性知识:dvh、aspect-ratio、backdrop-filter。万一真机出问题,直接给AI说“把XX属性换成兼容写法”,它能快速给你替换版本。多跑几次真机,你就能慢慢积累出一套自己的兼容清单。
6. 关于流程的几点心得
写了九篇Vibe Coding笔记,这个项目算是一个比较完整的缩影。游戏页面的布局开发用到的东西并不高级——Flex、Grid、vh/dvh、响应式单位,这些三年前的CSS教程里就有。但Vibe Coding真正改变的是把这些知识变成了一种“对话能力”。我不再需要从头到尾亲手敲完每一行,而是可以把主要精力放在描述需求、审查生成结果、修正细节上。这个转变听起来不大,实际跑起项目来省下的时间非常可观。
我个人的体会是,Vibe Coding生成游戏界面布局特别强,但前提是你要有一个“两层心智”:第一层是清楚页面应该长什么样,第二层是清楚代码应该怎么组织。第一层靠视觉审美和用户同理心,第二层靠最基本的HTML/CSS常识——你不需要像工程师一样手写全部代码,但你需要能一眼看出代码组织的味道对不对。
如果你也想练手,找一个你喜欢的小游戏,不管多简单都行,把它的页面拆成“信息、地图、控制”三个区域,然后用自然语言描述需求,让AI帮你搭建布局。过程中遇到问题就对照这篇笔记里的排查思路。跑通几个页面之后,你对Vibe Coding的掌控感会完全不一样——别人还在纠结怎么描述需求的时候,你已经能精确指出AI在哪一行出了问题。这种对代码的控制力,才是Vibe Coding真正值钱的地方。