ByteNoteByteNote
AI 生成的页面一片空白?问题多半出在 CDN
字

字节笔记本

2026年10月7日 · 约 7 分钟读完

AI 生成的页面一片空白?问题多半出在 CDN

API中转
¥120

拿一张产品官网截图丢给 AI,要它一比一还原出 HTML,大概是眼下最高频的 AI 编程场景之一。多数人会盯着「像不像」反复调提示词,但一次复刻某地震预警应用落地页的实践,卡在了一个更早的问题上:第一版压根没渲染出来,预览里只有一片空白。从白屏到最终对齐,三轮迭代暴露出两个最常见也最隐蔽的坑——看不见的依赖,和看不见的默认值。它们都不属于「提示词技巧」,而是前端常识在 AI 协作里的重新定价。

三轮迭代:CDN 白屏、默认背景、色板补齐

先看现场:三次反馈,三处病灶

复刻对象是典型的产品官网单页:顶部 logo 加一枚「Featured on Product Hunt」徽章;hero 区放主标题、副文案和黑色的 App Store 下载按钮;往下是应用截图预览;再往下是数据区——过去 24 小时 226 次地震、最近一次事件震级 2.2、深度 4 公里、数据源 EMSC——旁边配一块地图;FAQ 两栏;页脚压着二维码和版权信息。

AI 第一轮交出的代码结构其实没问题:各区块齐全、层级合理,用了 Tailwind 加一小段自定义 CSS。用户的反馈却只有一句:很差劲,没有样式,一版空白。第二轮换成全内联 CSS,页面立起来了,反馈变成:你没有注意背景色。第三轮补齐色板才算收敛。三处病灶依次是:依赖加载失败、色彩层级缺失,以及贯穿始终的验收方式。前两个值得逐个拆开。

白屏根因:CDN 脚本不是样式表

第一版的样式来自一行 <script src=".../tailwind.min.js"> 的 CDN 引用。这正是翻车的根源。很多人——包括这里的 AI——把 Tailwind 的 CDN 版当成「一份放在网上的 CSS」,实际完全不是:它是 Tailwind 的 Play CDN 方案,一段要在浏览器里现场运行的 JIT 编译器,先加载脚本,再扫描整棵 DOM、识别每个 class、现场生成样式表注入页面。

这条链路任何一环断掉,样式就整体归零:预览环境用沙箱 iframe 拦截外部脚本、页面带 CSP 策略、网络不通或 CDN 超时、脚本执行出错。而 AI 最常用的 artifact 预览、各类在线 playground,恰恰多是受限 iframe。更麻烦的是这种失败完全静默:没有报错弹窗,只有一片空白,和「AI 写错了」在表象上无法区分。

三条路线的取舍在这里一目了然。CDN 方案零构建、引一行就能跑,但依赖网络和脚本执行权限,只适合本地随手原型;构建期 Tailwind(PostCSS 或 Vite 插件)是生产正解,样式编译成静态 CSS,代价是要挂一套 node 工具链;而给「单文件、随处打开」的预览交付,唯一的稳解是内联 CSS——把样式全量写进 <style> 标签,零外部请求,丢进任何沙箱都能渲染。为预览环境生成的页面一律自包含,这条可以当铁律。

进阶的做法是分层兜底:先用一份无依赖的基础样式保证任何环境下内容可读、结构可辨,再在此之上叠加增强样式。这样即便某个外部资源真的加载失败,页面的下场也是「丑」而不是「空」——静默失败无法完全避免时,至少让降级体面。

零依赖版本:结构怎么钉牢

换成全内联 CSS 后,第二版要解决的是单文件页面的布局分工。横向对齐(header 左右分布、统计区两栏)交给 flex;FAQ 这类数量不定、两栏自适应的网格交给 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr))——容器够宽就并排,不够就自动落成一列,一行声明顶掉全部断点判断,是单文件页里性价比最高的响应式写法。整页再套一层 max-width 1200px 的居中容器收住视线,桌面端落地页的基本盘就有了。

资产照「先结构、后替换」的节奏走:应用截图和 logo 先用占位图顶着,地图先放一块灰色容器占位,真实实现留给 Leaflet 这类地图库按坐标画点;App Store 徽章、二维码同理。字体写成 Inter, Arial, sans-serif 这样的 fallback 栈,环境里没有 Inter 也不至于退化到无法阅读。到这一版,页面在任何预览环境里都能完整渲染——然后用户看了一眼:背景色不对。

下一坑:默认值是隐形的决策

人眼验收复刻页面时,最先挑出来的往往不是布局,而是整体色块。原始设计里 hero、数据区、FAQ 是纯白底,页脚是一层浅灰,地图容器是更深一档的灰;而刚修好白屏的版本大量依赖浏览器默认值,AI 也顺手给了「白底黑字的安全方案」,两边一比,观感立刻散掉。

修正的正确姿势不是「把颜色调一下」,而是先取色板:主背景 #FFFFFF、主文字 #333333、次要文字 #666666、页脚底 #F8F8F8、地图占位 #F0F0F0、品牌强调色 #FF9900(logo 文字)。然后每个 section 显式声明 background,不让任何区块依赖默认值。取色不需要专门工具,系统自带的数字测色计、浏览器开发者工具里的吸管,在原图上点一下就有色值。更值得做的是给色板分层:颜色按语义分成背景、文字、强调三组,而不是让十几个十六进制值散落在各处——命名即文档,后续无论是继续调样式还是迁移到任何框架的配置,这组令牌都能原样搬走。这一步本质是把截图里的视觉信息翻译成一组显式数值:布局信息(几栏、谁对齐谁)AI 从截图里能读得八九不离十,色阶这种低对比度信息却最容易被默认值吃掉;而人眼恰恰对整页色块最敏感,于是最不该出错的地方成了最先翻车的地方。

落地页结构与色板对照

把反馈磨成单点

回头看,这次复刻能三轮收敛,反馈的质量功不可没。「没有样式,一版空白」把问题钉在依赖加载上,「你没有注意背景色」把问题钉在色板上——每轮只打一个点,AI 修单点问题的命中率远高于「很差劲,重做」这类整体否定。整理成一份可复用的清单:

  1. 生成前先列 section 清单,让 AI 按清单搭骨架,而不是看图自由发挥;
  2. 给预览环境的交付一律零依赖单文件,CDN 只留给本地原型;
  3. 动手前先从截图取色,把色板当作和布局同级的输入;
  4. 图片、地图、二维码先占位后替换,别让资产阻塞结构验收;
  5. 每轮并排对比渲染结果与原图,一次只提一个最痛的问题。

并排对比不必讲究工具:浏览器开两个窗口,或把截图拖进画布和渲染结果叠着看,一眼就能锁定差异块,比在对话里来回拉扯省一半时间。

AI 出页面越来越快,但「像不像」的裁决权始终在人手里。这两课合起来其实是同一句话:别让任何东西留在默认值里——依赖要显式声明,颜色要显式声明,反馈也要显式到单点。做到这三条,截图还原就从碰运气变成一道可复现的工序。

相关文章

分享: