Design to code 技术
技术概述
在互联网时代,产品的开发与迭代速度都大大快于传统的应用开发。一个完整的产品开发周期,先由产品经理完成概念框图设计,然后交由UI设计师形成视觉设计稿,最后交给开发人员实现最终的产品功能。Design to Code负责将UI设计师的视觉稿,转化为前端代码,以供后续开发,这个环节架起了UI设计师与程序开发人员之间桥梁,让两类不同专业人,可以相互沟通,紧密合作。
示例:左图为设计师提供的网站视觉稿,右图为转化为html的部分代码
<body>
<div id="__next" data-reactroot="">
<div class="jsx-aab0212dbcb84404 design-to-code-container">
<div id="mobile-header" class="jsx-aab0212dbcb84404 mobile-header">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-mobilemenu ">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-top1">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-left-side"><a
class="jsx-c978c3fb180936e0 mobile-menu-light-link10" href="/"><img alt="teleporthq"
src="/Home/teleport-logo-dark-text.svg"
class="jsx-c978c3fb180936e0 mobile-menu-light-mobile-menu-logo"></a></div>
<div class="jsx-c978c3fb180936e0 mobile-menu-light-right-side">
<div class="jsx-c978c3fb180936e0 close-mobile-menu"><svg viewBox="0 0 1024 1024"
class="jsx-c978c3fb180936e0 close-mobile-menu-icon">
<title class="jsx-c978c3fb180936e0">clear, close</title>
<path d="M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z"
class="jsx-c978c3fb180936e0"></path>
</svg></div>
</div>
</div>
<div class="jsx-c978c3fb180936e0 mobile-menu-light-middle">
<div data-role="Accordion" class="jsx-c978c3fb180936e0 mobile-menu-light-product">
<div data-role="AccordionHeader" class="jsx-c978c3fb180936e0 accordion-header"><span
class="jsx-c978c3fb180936e0 mobile-menu-light-text10">Product</span><svg viewBox="0 0 1024 1024"
data-type="AccordionArrow" class="jsx-c978c3fb180936e0 accordion-arrow">
<path d="M298 426h428l-214 214z" class="jsx-c978c3fb180936e0"></path>
</svg></div>
<div data-role="AccordionContent"
class="jsx-c978c3fb180936e0 mobile-menu-light-content1 accordion-content"><a
class="jsx-c978c3fb180936e0" href="/professional-website-builder">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item10"><img alt="image"
src="/Home/Icons/bxs-widget.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image10"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Profesional website builder</span></div>
</a><a href="/ai-website-builder" target="_blank" rel="noreferrer noopener"
class="jsx-c978c3fb180936e0">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item11"><img alt="image"
src="/Home/Icons/bxs-detail2.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image11"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">AI website builder</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/headless-cms-integration">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item12"><img alt="image"
src="/cms-icon.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image12"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Headless CMS Integrations</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/website-localization">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item13"><img alt="image"
src="/Localization/localization1.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image13"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Localization</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/static-website-templates">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item14"><img alt="image"
src="/Home/Icons/bxs-layout1.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image14"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Static website templates</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/free-low-code-platform">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item15"><img alt="image"
src="/Home/Icons/bxs-devices.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image15"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Low-code development</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/real-time-code-collaboration">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item16"><img alt="image"
src="/Home/Icons/bxs-terminal.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image16"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Code collaboration</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/static-site-generator">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item17"><img alt="image"
src="/Home/Icons/bxl-react.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image17"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Code generators</span></div>
</a><a class="jsx-c978c3fb180936e0" href="/figma-export-to-html-plugin">
<div class="jsx-c978c3fb180936e0 mobile-menu-light-dropdown-item18"><img alt="image"
src="/Home/Icons/bxl-figma1.svg" class="jsx-c978c3fb180936e0 mobile-menu-light-image18"><span
class="jsx-c978c3fb180936e0 mobile-menu-link-black">Figma plugin</span></div>
</a></div>
UI设计稿转化为代码的工作,通常都是由前端开发人员来完成。但是这项工作繁琐重复,同时枯燥缺乏创新。如果可以将该工作自动化,不仅可以缩短设计与前端开发的鸿沟,减少大量重复劳动,也可以大幅降低前端工作的门槛,让一些初学者或设计师,快速地将设计稿转化为前端代码,实现产品原型的快速迭代。也可以提升多平台(iOS,Android,Web)的适配的开发效率。
通常Web页面相比移动端UI更为复杂,所以本文集中探讨将UI Design转化为Web代码的方法。
Design to Code的自动化方法有多年的探索,大致可以划分为几种
-
基于规则的方法:从特定格式的设计稿,如Figma,Sketch、Adobe XDsketch等,转化为前端代码。或是由低代码平台,将拖拽组件生成的UI自动转化为前端代码。
-
基于AI的方法:基于AI的方法有基于传统的CV方法,对设计稿中的视觉元素进行分类识别。近些年随着多模态大模型的发展,已可以实现图片转文本等能力,于是在design to code领域也有新的发展。
基于规则的Design to Code
TeleportHQ(https://teleporthq.io/) 是一款功能强大的低代码前端设计与开发平台,它提供了提供直观的拖拽式网站构建器,用户可简单地将元素拖放到页面上,快速搭建网页布局,无需复杂的代码编写。
在将用户构建的网站转化为code时,TeleportHQ首先会将包含有布局、样式的设计信息转换为一种通用的UIDL语言,这种语言采用类似下述的Json格式,来存储元素、样式等信息。
{
"name": "Simple Component",
"node": {
"type": "element",
"content": {
"elementType": "container",
"children": [
{
"type": "element",
"content": {
"elementType": "text",
"style": {
"margin": {
"type": "static",
"content": "10px"
},
"color": {
"type": "static",
"content": "red"
}
},
"children": [
{
"type": "static",
"content": "World!"
}
]
}
}
]
}
}
}
之后,TeleportHQ会根据UIDL,生成Html5+css,也能自动生成适用于多种 JavaScript 框架的代码,如 React、Next、Vue、Nuxt、Angular 等。这个生成代码的过程是递归遍历UIDL中的每个UI元素,根据编写好的规则,生成每个元素对应的框架代码。这个代码生成器已开源到github,可以供用户进行二次开发或扩展。(https://github.com/teleporthq/teleport-code-generators)
同时,TeleportHQ也提供了基于Figma的Design to code插件,可以将Figma的设计转化为代码。其基本的转换过程是,先将Figma的设计转化为TeleportHQ的UIDL,同时支持在TeleportHQ的可视化编辑器中进行调整修改,之后再转化为相应的代码。
从TeleportHQ导出Html
跟TeleportHQ类似的Design to code插件还有Anima(https://www.animaapp.com/),也可以将Figma插件转化为code。
基于规则的Design to code方法,依赖输入的设计稿包含完整的布局与样式信息,转换方法比较直接,根据样式信息来做规则转化,转换出的代码相对准确。但依赖规则进行转换的局限性也比较大。
- UI设计的工作,需要局限在特定的设计工具
- 转换出的代码质量依赖设计质量,不能自动转化为响应式布局的代码
基于AI的Design to Code
基于规则的方法,非常简单直观,但适用的范围受限。如果我们希望结合AI生成图片的能力来做网页设计,再将图片交由AI转换为代码,基于规则的方法,就不太灵活。我们需要考虑更通用的方法,能将图片转换为代码。
基于传统机器学习算法实现
-
CV:淘宝开源的,ms sketch2code
-
基于DL模型的pix2code
2017年Tony Beltramelli发表了一篇论文: pix2code: Generating Code from a Graphical User Interface Screenshoth,引起业界关注,论文使用深度学习技术将UI 截图识别生成 UI 结构描述,然后将 UI 结构描述转成 HTML 代码。这种方法实现了一个端到端模型,将设计稿图片转代码。作者将其工作开源到:https://github.com/tonybeltramelli/pix2code
模型结构
pix2code的模型借鉴了Image captioning的技术。Image captioning是输入一幅照片,输出一段文本描述照片中的内容。而design to code的过程,与其非常相似,同样是输入一幅照片,输入一段文本,而这段文本是我们想要的代码。
我们可以将这个过程拆分为3个子任务
- 理解图像的任务:根据输入的图片,推断出图片中的物体、身份、位置等信息(在这里则是按钮,图标,UI元素等信息)
- 理解语言的任务:可以理解语言并生成符合语法及语义的文本,在这里则是生成代码。
- 构建一个可以连接任务1和任务2的模型,将两者的能力结合起来,完成端到端的代码转换任务。
pix2code的模型结构如下:
pix2code的输入为UI图片以及context文本,输出为DSL语言,最后将DSL转换为多平台的前端代码,支持的前端平台包括iOS,Android和Web HTML。
DSL示例如下
- 模型的训练:
在训练阶段,输入的GUI图片会通过一个基于CNN的视觉模型进行编码,生成向量p。context则通过一个具有多层LSTM的语言模型进行编码,生成向量qt。context是一个基于DSL的token序列,每个token是一个基于DSL词典的one-hot编码向量。
2个编码模型生成特征向量p和qt后,进行拼接,生成向量rt,输入给后续的解码模型,解码模型由多层LSTM网络构成。最后在softmax层,每次sample一个token作为输出,softmax层的大小与DSL的词典大小相同。
- 模型的预测:
在预测阶段,输入的context的模型是上一次更新的token。模型最终输出的DSL文本序列,会通过一个基于规则的compiler将DSL转换为各个平台的前端代码。
- 数据集:
pix2code的数据集,由iOS,Android,Web三个平台的数据构成。以Web数据集为例,全部数据集由1742对图片和DSL文件构成,这些数据属于合成数据,并非真实数据。
数据实例如下
|```
header {btn-inactive, btn-active, btn-inactive, btn-inactive, btn-inactive}row {double {small-title, text, btn-orange}double {small-title, text, btn-green}}row {single {small-title, text, btn-green}}row {quadruple {small-title, text, btn-green}quadruple {small-title, text, btn-green}quadruple {small-title, text, btn-orange}quadruple {small-title, text, btn-red}} | ![]() |
---|
- 生成效果测试
在作者的论文中,对生成代码进行了效果测试,准确率可以达到77%
接下来我们在实际应用场景中进行测试,将下面的图片输入给训练好的pix2code,让其生成HTML代码
<html>
<header>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<style>
.header{margin:20px 0}nav ul.nav-pills li{background-color:#333;border-radius:4px;margin-right:10px}.col-lg-3{width:24%;margin-right:1.333333%}.col-lg-6{width:49%;margin-right:2%}.col-lg-12,.col-lg-3,.col-lg-6{margin-bottom:20px;border-radius:6px;background-color:#f5f5f5;padding:20px}.row .col-lg-3:last-child,.row .col-lg-6:last-child{margin-right:0}footer{padding:20px 0;text-align:center;border-top:1px solid #bbb}
</style>
<title>Scaffold</title>
</header>
<body>
<main class="container">
<div class="header clearfix">
<nav>
<ul class="nav nav-pills pull-left">
<li><a href="#">Zsoiyo Oms</a></li>
<li class="active"><a href="#">Kvzzcl Lgw</a></li>
<li><a href="#">Ppbo Ocdif</a></li>
<li><a href="#">Xqlyxkm Ma</a></li>
<li><a href="#">Rppe Enobt</a></li>
</ul>
</nav>
</div>
<div class="row"><div class="col-lg-12">
<h4>Ssfhi</h4><p>eolld l alnrgmrxhadpsdak dcfudte x lsakvmu cxwlagnx qaaw</p>
<a class="btn btn-success" href="#" role="button">Ncjpmq Qbq</a>
</div>
</div>
<div class="row"><div class="col-lg-6">
<h4>Nmwga</h4><p>zkmgj cot facwccevzzrpbvszxf txgrcdjiwixet i kkpwaxeqq</p>
<a class="btn btn-success" href="#" role="button">Etban Nled</a>
</div>
<div class="col-lg-6">
<h4>Idkpc</h4><p>iostghxt pv uzdoaa p rohkzxttijgreknlolyp naumyhrpifso</p>
<a class="btn btn-success" href="#" role="button">Nbb Bbakmj</a>
</div>
</div>
<div class="row"><div class="col-lg-3">
<h4>Egwfm</h4><p>fi spqhdnsklxnnfhkerjekyt tzhz y ccxtspygtighnkcilm fg</p>
<a class="btn btn-success" href="#" role="button">Zumelfy Yw</a>
</div>
<div class="col-lg-3">
<h4>Vppuz</h4><p>pb rwpcjyj hup nemtzh djwqt otsqsodsokyi ikivacon qvpqpg</p>
<a class="btn btn-success" href="#" role="button">Sznrqi Idm</a>
</div>
<div class="col-lg-3">
<h4>Ytqdc</h4><p>cdxc rfbkn qlcmxfiqu sgsajvnjqcsf ymr wf ndnwdvlfugpxia</p>
<a class="btn btn-success" href="#" role="button">Qa Aorqvge</a>
</div>
<div class="col-lg-3">
<h4>Hldfo</h4><p>lhv ybey ztvr erxjqv qbqnyehyms uh tlixrqznlfsssfnze jzr</p>
<a class="btn btn-success" href="#" role="button">Lswb Bvxeb</a>
</div>
</div>
<div class="row"><div class="col-lg-12">
<h4>Gnudw</h4><p>cjnvscsvjl sbxbnbdtmrwms d rmmumnzskwhv qj qbxvpga ohtjb</p>
<a class="btn btn-success" href="#" role="button">Ihrkqxl Lx</a>
</div>
</div>
<div class="row"><div class="col-lg-6">
<h4>Kbuig</h4><p>avat ka nmdayn pynh xk inntfoaxjstpyuswe a lmwzjgthlhjew</p>
<a class="btn btn-success" href="#" role="button">Cjenvp Pqs</a>
</div>
<div class="col-lg-6">
<h4>Urxdq</h4><p>sflbx qloesavh mbiqozvu iayiqws kbsyrnyazzomdc ayunig jl</p>
<a class="btn btn-success" href="#" role="button">Zlhdww Wkv</a>
</div>
</div>
<footer class="footer">
<p>© Tony Beltramelli 2017</p>
</footer>
</main>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</body>
</html>
从结果来看,是非常的糟糕,看不出与原始页面有任何关系。Pix2code在paper中提及的准确率仅能说明在它特定的测试集上有效,在实际网页上效果非常差,无法用于实际工作。
pix2code目前主要还是作为一个研究项目开源,在实际应用中并不理想。这可能受限于训练数据偏少,也可能是由于使用的训练数据为合成数据,非实际数据,因而与在实际应用中的表现与测试结果相差很大。
基于多模态LLM的实现
随着大语言模型的能力越来越强,开始出现使用大模型来做design to code的转换工作。
目前的视觉LLM已经可以根据用户输入的图片和文字,回答文字结果,那么设计稿转代码的工作也是类似的,将设计稿图片输入到LLM,让模型根据指令,生成文字序列(code)
开源软件screenshot-to-code(https://github.com/abi/screenshot-to-code),通过编写prompt,利用多模态大模型来实现,例如,我们将下面的prompt以及图片输入给GPT-4o,会生成相应的网页代码
You are an expert CSS developer
You take screenshots of a reference web page from the user, and then build single page apps
using CSS, HTML and JS.
You might also be given a screenshot(The second image) of a web page that you have already built, and asked to
update it to look more like the reference image(The first image).
- Make sure the app looks exactly like the screenshot.
- Pay close attention to background color, text color, font size, font family,
padding, margin, border, etc. Match the colors and sizes exactly.
- Use the exact text from the screenshot.
- Do not add comments in the code such as "<!-- Add other navigation links as needed -->" and "<!-- ... other news items ... -->" in place of writing the full code. WRITE THE FULL CODE.
- Repeat elements as needed to match the screenshot. For example, if there are 15 items, the code should have 15 items. DO NOT LEAVE comments like "<!-- Repeat for each news item -->" or bad things will happen.
- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later.
In terms of libraries,
- You can use Google Fonts
- Font Awesome for icons: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"></link>
Return only the full code in <html></html> tags.
Do not include markdown "```" or "```html" at the start or end.
- 与LLM交互的Prompt示例如下
{
"prompt": [
{
"role": "system",
"content": "\nYou are an expert CSS developer\nYou take screenshots of a reference web page from the user, and then build single page apps \nusing CSS, HTML and JS.\nYou might also be given a screenshot(The second image) of a web page that you have already built, and asked to\nupdate it to look more like the reference image(The first image).\n\n- Make sure the app looks exactly like the screenshot.\n- Pay close attention to background color, text color, font size, font family, \npadding, margin, border, etc. Match the colors and sizes exactly.\n- Use the exact text from the screenshot.\n- Do not add comments in the code such as \"<!-- Add other navigation links as needed -->\" and \"<!-- ... other news items ... -->\" in place of writing the full code. WRITE THE FULL CODE.\n- Repeat elements as needed to match the screenshot. For example, if there are 15 items, the code should have 15 items. DO NOT LEAVE comments like \"<!-- Repeat for each news item -->\" or bad things will happen.\n- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later.\n\nIn terms of libraries,\n\n- You can use Google Fonts\n- Font Awesome for icons: <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css\"></link>\n\nReturn only the full code in <html></html> tags.\nDo not include markdown \"```\" or \"```html\" at the start or end.\n"
},
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,iVBORw0KGgoAAAAN...",
"detail": "high"
}
},
{
"type": "text",
"text": "\nGenerate code for a web page that looks exactly like this.\n"
}
]
}
],
"completion": "<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n ..."
}
- GPT-4o生成的HTML网页效果如下:
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>
TeleportHQ
</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<style>
body {
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 40px;
border-bottom: 1px solid #eaeaea;
}
.navbar .logo {
display: flex;
align-items: center;
}
.navbar .logo img {
height: 24px;
margin-right: 8px;
}
.navbar .menu {
display: flex;
align-items: center;
}
.navbar .menu a {
margin: 0 15px;
text-decoration: none;
color: #000;
font-weight: 500;
}
.navbar .menu a.new {
background-color: #e0d7ff;
color: #6b47dc;
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
margin-left: 5px;
}
.navbar .menu .cta {
background-color: #6b47dc;
color: #fff;
padding: 10px 20px;
border-radius: 5px;
text-decoration: none;
margin-left: 20px;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 60px 40px;
}
.content .text {
max-width: 500px;
}
.content .text h1 {
font-size: 48px;
font-weight: 700;
margin: 0 0 20px;
line-height: 1.2;
}
.content .text p {
font-size: 18px;
line-height: 1.6;
margin: 0 0 20px;
}
.content .text .cta {
background-color: #000;
color: #fff;
padding: 15px 30px;
border-radius: 5px;
text-decoration: none;
font-weight: 700;
}
.content .image {
position: relative;
width: 600px;
height: 400px;
}
.content .image img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div class="navbar">
<div class="logo">
<img alt="TeleportHQ logo with colorful abstract shapes" src="https://placehold.co/24x24"/>
<span>
teleport
<span style="font-size: 10px;">
HQ
</span>
</span>
</div>
<div class="menu">
<a href="#">
Product
</a>
<a class="new" href="#">
New
</a>
<a href="#">
Services
</a>
<a href="#">
Resources
</a>
<a href="#">
White Label Editor
</a>
<a href="#">
Pricing
</a>
<a href="#">
Login
</a>
<a class="cta" href="#">
Start for free
</a>
</div>
</div>
<div class="content">
<div class="text">
<h1>
Translate design to code in an automated way
</h1>
<p>
TeleportHQ is a design-to-code tool that helps you build products faster and turn them into HTML.
</p>
<p>
With our platform, you don’t need to write code, but developers can create a fully functional website or app based on a Figma design, which they can export as clean code.
</p>
<a class="cta" href="#">
Start building
</a>
</div>
<div class="image">
<img alt="Screenshot of a design tool interface with various UI elements and code editor" src="https://placehold.co/600x400"/>
</div>
</div>
</body>
</html>
生成的效果还是非常不错的,图片中的文字、导航菜单、按钮等元素识别基本准确,整体结构基本正确。并且可以识别出导航栏的阴影细节。但我们也可以看到有一些不完美的地方,如导航栏的login按钮被识别为了菜单项,"Start Building"按钮的圆角样式也没有复原出来,需要后期人工调整。
按照screenshot-to-code的评估,Claude Sonnet 3.7是它所支持的模型中表现最好的,我们再尝试使用claude重新生成一下这个页面。
<html>
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>
TeleportHQ - Design to Code
</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Inter', sans-serif;
}
body {
background-color: #ffffff;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 80px;
background-color: #ffffff;
}
.logo {
display: flex;
align-items: center;
}
.logo img {
height: 40px;
}
.nav-links {
display: flex;
align-items: center;
gap: 30px;
}
.nav-item {
font-size: 16px;
font-weight: 500;
color: #333;
text-decoration: none;
display: flex;
align-items: center;
}
.nav-item i {
margin-left: 5px;
}
.new-badge {
background-color: #7c4dff;
color: white;
font-size: 12px;
padding: 2px 6px;
border-radius: 4px;
margin-right: 8px;
}
.login-btn {
background-color: #e6e6e6;
color: #333;
padding: 12px 24px;
border-radius: 6px;
text-decoration: none;
font-weight: 500;
margin-right: 10px;
}
.start-btn {
background-color: #7c4dff;
color: white;
padding: 12px 24px;
border-radius: 6px;
text-decoration: none;
font-weight: 500;
}
.hero-section {
display: flex;
padding: 40px 80px;
align-items: center;
justify-content: space-between;
}
.hero-content {
max-width: 600px;
}
.hero-title {
font-size: 60px;
font-weight: 700;
line-height: 1.1;
margin-bottom: 30px;
color: #111;
}
.hero-description {
font-size: 18px;
line-height: 1.6;
color: #444;
margin-bottom: 30px;
}
.hero-image {
max-width: 650px;
position: relative;
}
.hero-image img {
width: 100%;
border-radius: 8px;
}
.start-building-btn {
background-color: #111;
color: white;
padding: 16px 32px;
border-radius: 50px;
text-decoration: none;
font-weight: 500;
font-size: 18px;
display: inline-block;
}
.built-badge {
position: absolute;
bottom: 20px;
right: 20px;
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px 20px;
border-radius: 8px;
display: flex;
align-items: center;
gap: 10px;
}
.built-badge img {
width: 24px;
height: 24px;
}
.pink-blob {
position: absolute;
top: -100px;
right: -100px;
width: 500px;
height: 500px;
background: radial-gradient(circle, rgba(255,0,255,0.5) 0%, rgba(255,0,255,0) 70%);
border-radius: 50%;
z-index: -1;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="logo">
<img alt="TeleportHQ logo with colorful geometric shapes and the text 'teleport HQ'" src="https://placehold.co/200x50/7c4dff/ffffff?text=teleportHQ"/>
</div>
<div class="nav-links">
<a class="nav-item" href="#">
Product
<i class="fas fa-chevron-down">
</i>
</a>
<a class="nav-item" href="#">
<span class="new-badge">
NEW
</span>
Services
<i class="fas fa-chevron-down">
</i>
</a>
<a class="nav-item" href="#">
Resources
<i class="fas fa-chevron-down">
</i>
</a>
<a class="nav-item" href="#">
White Label Editor
</a>
<a class="nav-item" href="#">
Pricing
</a>
<a class="login-btn" href="#">
Login
</a>
<a class="start-btn" href="#">
Start for free
</a>
</div>
</nav>
<div class="hero-section">
<div class="hero-content">
<h1 class="hero-title">
Translate design to code in an automated way
</h1>
<p class="hero-description">
TeleportHQ is a design-to-code tool that helps you build products faster and turn them into HTML.
</p>
<p class="hero-description">
With our platform, you don't need to write code, but developers can create a fully functional website or app based on a Figma design, which they can export as clean code.
</p>
<a class="start-building-btn" href="#">
Start building
</a>
</div>
<div class="hero-image">
<div class="pink-blob">
</div>
<img alt="TeleportHQ interface showing a design-to-code conversion with a headphones website design on the right and code editor on the left, featuring blue headphones and CSS code" src="https://placehold.co/650x550/333/ffffff?text=TeleportHQ+Interface"/>
<div class="built-badge">
<img alt="TeleportHQ icon" src="https://placehold.co/24x24/ffffff/7c4dff?text=T"/>
Built in TeleportHQ
</div>
</div>
</div>
</body>
</html>
claude生成页面的效果可以用惊艳来形容,导航栏的细节被完美还原,按钮的圆角样式也与原图保持一致,甚至尝试复原右侧背景。需要后期人工调整的工作非常少了。
接下来我们尝试一个更有挑战的复杂页面,这个页面包含有非常多的UI元素,各种卡片的样式也非常多样。我们让大模型来尝试做HTML的转换工作
- GPT-4o生成的页面
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>
Web Page
</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap" rel="stylesheet"/>
<style>
body {
margin: 0;
font-family: 'Noto Sans SC', sans-serif;
background-color: #f5f5f5;
}
.header {
background-image: url('https://placehold.co/1920x300?text=Mountain+Sunset+Background');
background-size: cover;
background-position: center;
padding: 20px;
color: white;
}
.header .search-bar {
display: flex;
justify-content: center;
margin-top: 20px;
}
.header input[type="text"] {
width: 50%;
padding: 10px;
border-radius: 20px;
border: none;
font-size: 16px;
}
.header .icons {
display: flex;
justify-content: center;
margin-top: 20px;
}
.header .icons i {
margin: 0 10px;
font-size: 24px;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 20px;
}
.card {
background-color: white;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: 10px;
overflow: hidden;
width: 300px;
}
.card img {
width: 100%;
height: auto;
}
.card-content {
padding: 15px;
}
.card-content h3 {
margin: 0;
font-size: 18px;
color: #333;
}
.card-content p {
margin: 10px 0;
color: #666;
}
.card-content .actions {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-content .actions i {
color: #999;
}
.card-content .actions span {
color: #999;
font-size: 14px;
}
</style>
</head>
<body>
<div class="header">
<div class="search-bar">
<input placeholder="搜索工作和网页" type="text"/>
</div>
<div class="icons">
<i class="fab fa-microsoft">
</i>
<i class="fab fa-kickstarter">
</i>
<i class="fab fa-jira">
</i>
<i class="fab fa-google">
</i>
<i class="fab fa-facebook">
</i>
<i class="fab fa-twitter">
</i>
<i class="fas fa-plus">
</i>
</div>
</div>
<div class="content">
<div class="card">
<img alt="Game Advertisement" src="https://placehold.co/300x150?text=Game+Advertisement"/>
<div class="card-content">
<h3>
散人都能爽玩!
</h3>
<p>
新版本上线,快来体验!
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
16
</span>
</div>
</div>
</div>
<div class="card">
<img alt="News Image" src="https://placehold.co/300x150?text=News+Image"/>
<div class="card-content">
<h3>
刚刚,成龙发文!
</h3>
<p>
关注热点,了解更多。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
7
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Map Image" src="https://placehold.co/300x150?text=Map+Image"/>
<div class="card-content">
<h3>
交通拥堵
</h3>
<p>
实时路况,提前规划。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
41
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Weather Image" src="https://placehold.co/300x150?text=Weather+Image"/>
<div class="card-content">
<h3>
北京 -1°C
</h3>
<p>
天气预报,及时了解。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
23
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Food Image" src="https://placehold.co/300x150?text=Food+Image"/>
<div class="card-content">
<h3>
营养还是蒸的好!
</h3>
<p>
推荐5道蒸菜做法,清单健康不上火。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
6
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Technology Image" src="https://placehold.co/300x150?text=Technology+Image"/>
<div class="card-content">
<h3>
这还咋呼?华为Pura 80 Ultra配置曝光,写着“高通”俩字
</h3>
<p>
最新科技资讯,了解更多。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
14
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Car Image" src="https://placehold.co/300x150?text=Car+Image"/>
<div class="card-content">
<h3>
A、B、C、D级车是什么鬼?这次给你讲清楚
</h3>
<p>
汽车知识,轻松掌握。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
9
</span>
</div>
</div>
</div>
<div class="card">
<img alt="Earth Image" src="https://placehold.co/300x150?text=Earth+Image"/>
<div class="card-content">
<h3>
地球在宇宙中的详细地址,到底藏在这颗“蓝色星球”在哪里?
</h3>
<p>
探索宇宙,了解地球。
</p>
<div class="actions">
<i class="fas fa-heart">
</i>
<span>
8
</span>
</div>
</div>
</div>
</div>
</body>
</html>
这次GPT-4o生成的网页与原图相差甚远,仅有少量的UI元素,如搜索框,被正确地识别出来,整体结构也与原图差别很大,在复杂UI的生成方面,无法达到实用的效果。
我们再来看下Claude生成的结果
<html>
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>
MSN China
</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', Arial, sans-serif;
}
body {
background-image: url('https://placehold.co/1920x1080/007bff/ffffff?text=Sunset+Mountain+Background');
background-size: cover;
background-position: center;
background-attachment: fixed;
color: #333;
}
.top-bar {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 10px 20px;
color: white;
}
.top-bar .city {
margin-right: 10px;
}
.top-bar .temp {
margin-right: 10px;
display: flex;
align-items: center;
}
.top-bar .temp i {
color: #f8c01d;
margin-right: 5px;
}
.top-bar .settings {
margin-left: 10px;
}
.search-container {
display: flex;
justify-content: center;
margin: 20px 0;
}
.search-box {
display: flex;
width: 60%;
max-width: 600px;
}
.search-input {
flex: 1;
padding: 10px 15px;
border: none;
border-radius: 20px 0 0 20px;
outline: none;
font-size: 14px;
}
.search-button {
background-color: #0078d4;
color: white;
border: none;
border-radius: 0 20px 20px 0;
padding: 0 15px;
cursor: pointer;
}
.app-icons {
display: flex;
justify-content: center;
margin: 20px 0;
}
.app-icon {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 10px;
color: white;
text-decoration: none;
font-size: 12px;
}
.icon-circle {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 5px;
}
.blue-bg {
background-color: #0078d4;
}
.black-bg {
background-color: #000;
}
.red-bg {
background-color: #e62117;
}
.orange-bg {
background-color: #ff6700;
}
.green-bg {
background-color: #00a651;
}
.gray-bg {
background-color: #767676;
}
.teal-bg {
background-color: #00a99d;
}
.add-bg {
background-color: rgba(255, 255, 255, 0.2);
}
.quick-links {
display: flex;
justify-content: center;
margin: 20px 0;
flex-wrap: wrap;
}
.quick-link {
display: flex;
align-items: center;
margin: 0 10px;
color: white;
text-decoration: none;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 5px 15px;
border-radius: 20px;
margin-bottom: 10px;
}
.quick-link i {
margin-right: 5px;
}
.content-container {
background-color: white;
margin: 0 auto;
max-width: 1200px;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.nav-tabs {
display: flex;
background-color: #f8f8f8;
border-bottom: 1px solid #ddd;
padding: 0 20px;
}
.nav-tab {
padding: 10px 15px;
cursor: pointer;
font-size: 14px;
color: #666;
}
.nav-tab.active {
color: #0078d4;
border-bottom: 2px solid #0078d4;
}
.content-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 15px;
padding: 15px;
}
.card {
background-color: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
position: relative;
}
.card-large {
grid-column: span 6;
grid-row: span 2;
}
.card-medium {
grid-column: span 3;
grid-row: span 2;
}
.card-small {
grid-column: span 3;
grid-row: span 1;
}
.card-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-large .card-image {
height: 300px;
}
.card-content {
padding: 10px;
}
.card-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 5px;
}
.card-source {
font-size: 12px;
color: #666;
display: flex;
align-items: center;
margin-bottom: 5px;
}
.card-source img {
width: 16px;
height: 16px;
border-radius: 50%;
margin-right: 5px;
}
.card-time {
font-size: 12px;
color: #999;
margin-left: 5px;
}
.card-actions {
display: flex;
justify-content: space-between;
padding: 5px 10px;
color: #666;
font-size: 12px;
}
.card-action {
display: flex;
align-items: center;
}
.card-action i {
margin-right: 3px;
}
.news-list {
grid-column: span 3;
display: flex;
flex-direction: column;
}
.news-item {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.news-number {
color: #ff6700;
font-weight: bold;
margin-right: 10px;
min-width: 15px;
}
.news-title {
font-size: 14px;
flex: 1;
}
.weather-card {
background-color: #0078d4;
color: white;
padding: 15px;
}
.weather-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.weather-temp {
font-size: 36px;
font-weight: bold;
display: flex;
align-items: center;
}
.weather-icon {
font-size: 24px;
margin-right: 5px;
color: #f8c01d;
}
.weather-forecast {
display: flex;
justify-content: space-between;
margin-top: 15px;
}
.forecast-day {
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
}
.stock-card {
padding: 15px;
}
.stock-item {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.stock-name {
font-size: 14px;
}
.stock-price {
font-size: 14px;
}
.stock-change {
font-size: 12px;
color: #ff4d4f;
display: flex;
align-items: center;
}
.stock-change.positive {
color: #52c41a;
}
.calendar-card {
padding: 15px;
}
.calendar-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.calendar-date {
font-size: 18px;
font-weight: bold;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
margin-top: 10px;
}
.calendar-day {
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
padding: 5px;
}
.calendar-day.today {
background-color: #0078d4;
color: white;
border-radius: 50%;
}
.ad-label {
position: absolute;
bottom: 5px;
right: 5px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
font-size: 10px;
padding: 2px 5px;
border-radius: 2px;
}
.more-actions {
display: flex;
justify-content: center;
margin: 10px 0;
}
.more-button {
background-color: #f0f0f0;
border: none;
padding: 5px 15px;
border-radius: 15px;
margin: 0 5px;
font-size: 12px;
cursor: pointer;
}
.more-button i {
margin-right: 5px;
}
.news-source-list {
padding: 10px;
}
.news-source-item {
display: flex;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.news-source-icon {
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 10px;
background-color: #f0f0f0;
display: flex;
justify-content: center;
align-items: center;
}
.news-source-name {
font-size: 14px;
flex: 1;
}
.add-button {
color: #999;
cursor: pointer;
}
.traffic-map {
height: 150px;
background-color: #f0f0f0;
position: relative;
}
.traffic-info {
position: absolute;
bottom: 10px;
left: 10px;
background-color: white;
padding: 5px 10px;
border-radius: 5px;
font-size: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.traffic-time {
color: #ff6700;
font-weight: bold;
font-size: 16px;
}
.game-ad {
position: relative;
}
.game-title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 36px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.game-subtitle {
position: absolute;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 18px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.custom-tabs {
display: flex;
margin-bottom: 10px;
}
.custom-tab {
padding: 5px 10px;
font-size: 12px;
cursor: pointer;
}
.custom-tab.active {
border-bottom: 2px solid #0078d4;
color: #0078d4;
}
.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
</style>
</head>
<body>
<div class="top-bar">
<div class="city">
北京市
</div>
<div class="temp">
<i class="fas fa-sun">
</i>
-1°C
</div>
<div class="settings">
<i class="fas fa-cog">
</i>
</div>
</div>
<div class="search-container">
<div class="search-box">
<input class="search-input" placeholder="搜索工作和网页" type="text"/>
<button class="search-button">
<i class="fas fa-search">
</i>
</button>
</div>
</div>
<div class="app-icons">
<a class="app-icon" href="#">
<div class="icon-circle blue-bg">
<i class="fab fa-edge">
</i>
</div>
<span>
Microsoft Edge
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle black-bg">
<i class="fab fa-xbox">
</i>
</div>
<span>
Xbox
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle red-bg">
<i class="fas fa-shopping-bag">
</i>
</div>
<span>
京东
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle orange-bg">
<i class="fas fa-user">
</i>
</div>
<span>
淘宝
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle green-bg">
<i class="fas fa-comment">
</i>
</div>
<span>
微信公众号
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle gray-bg">
<i class="fas fa-file">
</i>
</div>
<span>
Microsoft 365
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle teal-bg">
<i class="fas fa-cloud">
</i>
</div>
<span>
微软云服务平台
</span>
</a>
<a class="app-icon" href="#">
<div class="icon-circle add-bg">
<i class="fas fa-plus">
</i>
</div>
<span>
添加应用
</span>
</a>
</div>
<div class="quick-links">
<a class="quick-link" href="#">
<i class="fas fa-search">
</i>
<span>
必应搜索
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-music">
</i>
<span>
抖音
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-shopping-cart">
</i>
<span>
京东
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-video">
</i>
<span>
哔哩
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-gamepad">
</i>
<span>
5177游戏
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-cloud">
</i>
<span>
智慧内容
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-map-marker-alt">
</i>
<span>
美团外卖
</span>
</a>
<a class="quick-link" href="#">
<i class="fas fa-ellipsis-h">
</i>
<span>
更多
</span>
</a>
</div>
<div class="content-container">
<div class="nav-tabs">
<div class="nav-tab active">
<img alt="MSN Logo" src="https://placehold.co/20x20/0078d4/ffffff?text=MSN" style="width: 20px; height: 20px; margin-right: 5px;"/>
首页
</div>
<div class="nav-tab">
热点
</div>
<div class="nav-tab">
财经
</div>
<div class="nav-tab">
体育
</div>
<div class="nav-tab">
娱乐
</div>
<div class="nav-tab">
天气
</div>
<div class="nav-tab">
体育
</div>
<div class="nav-tab">
小视频
</div>
<div class="nav-tab">
财经
</div>
<div class="nav-tab">
电视
</div>
<div class="nav-tab">
购物
</div>
<div class="nav-tab">
健康
</div>
<div class="nav-tab">
交通
</div>
<div class="nav-tab">
大众汽车
</div>
<div class="nav-tab">
日历
</div>
</div>
<div class="more-actions">
<button class="more-button">
<i class="fas fa-sync-alt">
</i>
更新内容
</button>
<button class="more-button">
<i class="fas fa-cog">
</i>
个性化设置
</button>
</div>
<div class="content-grid">
<!-- Game Ad Card -->
<div class="card card-large game-ad">
<img alt="传奇游戏广告展示古代中国风格的游戏场景,展示了宫殿和角色" class="card-image" src="https://placehold.co/600x300/ff6700/ffffff?text=传奇游戏广告"/>
<div class="game-title">
传奇3
</div>
<div class="game-subtitle">
全新2025版本
</div>
<div class="card-content">
<div class="card-source">
<img alt="游戏图标" src="https://placehold.co/16x16/ff6700/ffffff?text=游戏"/>
<span>
官方推荐·新游推荐
</span>
</div>
<div class="card-title">
散人都能爽玩!
</div>
</div>
<div class="ad-label">
广告
</div>
</div>
<!-- News Source List -->
<div class="card news-list">
<div style="padding: 10px; display: flex; justify-content: space-between; align-items: center;">
<span style="font-weight: bold;">
为你推荐
</span>
<i class="fas fa-ellipsis-h">
</i>
</div>
<div class="news-source-list">
<div class="news-source-item">
<div class="news-source-icon" style="background-color: #e62117; color: white;">
新
</div>
<div class="news-source-name">
新华社
</div>
<div class="add-button">
<i class="fas fa-plus">
</i>
</div>
</div>
<div class="news-source-item">
<div class="news-source-icon" style="background-color: #ff6700; color: white;">
人
</div>
<div class="news-source-name">
人民网
</div>
<div class="add-button">
<i class="fas fa-plus">
</i>
</div>
</div>
<div class="news-source-item">
<div class="news-source-icon" style="background-color: #0078d4; color: white;">
日
</div>
<div class="news-source-name">
每日经济新闻
</div>
<div class="add-button">
<i class="fas fa-plus">
</i>
</div>
</div>
<div class="news-source-item">
<div class="news-source-icon" style="background-color: #52c41a; color: white;">
生
</div>
<div class="news-source-name">
生活小课堂
</div>
<div class="add-button">
<i class="fas fa-plus">
</i>
</div>
</div>
<div class="news-source-item">
<div class="news-source-icon" style="background-color: #e62117; color: white;">
IT
</div>
<div class="news-source-name">
IT之家
</div>
<div class="add-button">
<i class="fas fa-plus">
</i>
</div>
</div>
</div>
<div style="padding: 10px; text-align: center; color: #0078d4; font-size: 12px;">
<i class="fas fa-cog">
</i>
个性化资讯推荐
</div>
</div>
<!-- News Card -->
<div class="card card-medium">
<img alt="水滴特写镜头,展示水滴的晶莹剔透和光影效果" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=水滴特写"/>
<div class="card-content">
<div class="card-source">
<img alt="人民网图标" src="https://placehold.co/16x16/ff6700/ffffff?text=人民"/>
<span>
人民网网
</span>
<span class="card-time">
· 9小时
</span>
</div>
<div class="card-title">
0.1秒的水滴特写 治愈了12版
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
181
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Food Recipe Card -->
<div class="card card-medium">
<img alt="一碗美味的肉丸,配有蔬菜和汤汁,看起来非常诱人" class="card-image" src="https://placehold.co/400x200/52c41a/ffffff?text=美食肉丸"/>
<div class="card-content">
<div class="card-source">
<img alt="美食频道图标" src="https://placehold.co/16x16/52c41a/ffffff?text=美食"/>
<span>
美食频道
</span>
<span class="card-time">
· 17小时
</span>
</div>
<div class="card-title">
营养还是蒸的好!推荐5道蒸菜做法,清单健康不上火
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
7
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- City View Card -->
<div class="card card-medium">
<img alt="城市全景,展示了城市的天际线和周围的山脉" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=城市风景"/>
<div class="card-content">
<div class="card-source">
<img alt="旅游频道图标" src="https://placehold.co/16x16/0078d4/ffffff?text=旅游"/>
<span>
旅游频道
</span>
<span class="card-time">
· 23小时
</span>
</div>
<div class="card-title">
重庆真把广州给PK掉了?
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
23
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Game Ad Card -->
<div class="card card-small">
<img alt="游戏广告展示了一个肌肉发达的战士角色" class="card-image" src="https://placehold.co/400x200/e62117/ffffff?text=游戏广告"/>
<div class="card-content">
<div class="card-source">
<span>
传奇游戏
</span>
</div>
<div class="card-title">
2025传奇新版本
</div>
</div>
<div class="ad-label">
广告
</div>
</div>
<!-- Weather Card -->
<div class="card card-small weather-card">
<div class="weather-header">
<div>
<i class="fas fa-map-marker-alt">
</i>
北京市
</div>
<div>
预报
</div>
</div>
<div class="weather-temp">
<i class="weather-icon fas fa-moon">
</i>
-1°C
</div>
<div>
预报信息
</div>
<div class="weather-forecast">
<div class="forecast-day">
<div>
今天
</div>
<i class="fas fa-sun" style="color: #f8c01d;">
</i>
<div>
0°
</div>
</div>
<div class="forecast-day">
<div>
周五
</div>
<i class="fas fa-cloud-sun" style="color: #f8c01d;">
</i>
<div>
5°
</div>
</div>
<div class="forecast-day">
<div>
周六
</div>
<i class="fas fa-cloud" style="color: #f8c01d;">
</i>
<div>
6°
</div>
</div>
<div class="forecast-day">
<div>
周日
</div>
<i class="fas fa-cloud" style="color: #f8c01d;">
</i>
<div>
8°
</div>
</div>
<div class="forecast-day">
<div>
周一
</div>
<i class="fas fa-sun" style="color: #f8c01d;">
</i>
<div>
10°
</div>
</div>
</div>
<div style="text-align: right; font-size: 12px; margin-top: 10px;">
查看详细预报
</div>
</div>
<!-- Hot News List -->
<div class="card news-list">
<div style="padding: 10px; display: flex; justify-content: space-between; align-items: center;">
<span style="font-weight: bold; color: #ff6700;">
热搜
</span>
<i class="fas fa-ellipsis-h">
</i>
</div>
<div class="news-source-list">
<div class="news-item">
<div class="news-number">
1
</div>
<div class="news-title">
小米SU7过程时速最高限速?官方:不实
</div>
</div>
<div class="news-item">
<div class="news-number">
2
</div>
<div class="news-title">
苹果将推出iPhone最全面料
</div>
</div>
<div class="news-item">
<div class="news-number">
3
</div>
<div class="news-title">
《崩坏3》将全球公测!!首测TOP10
</div>
</div>
<div class="news-item">
<div class="news-number">
4
</div>
<div class="news-title">
国家统计局:1月CPI同比上涨0.5%
</div>
</div>
<div class="news-item">
<div class="news-number">
5
</div>
<div class="news-title">
数据显示中国影视房屋销售增长
</div>
</div>
<div class="news-item">
<div class="news-number">
6
</div>
<div class="news-title">
有人花1亿购买DeepSeek教育资源
</div>
</div>
</div>
</div>
<!-- Bedroom Renovation Card -->
<div class="card card-small">
<img alt="一间精心装修的卧室,带有床、窗帘和温馨的灯光" class="card-image" src="https://placehold.co/400x200/f8c01d/ffffff?text=卧室装修"/>
<div class="card-content">
<div class="card-source">
<img alt="家居小课堂图标" src="https://placehold.co/16x16/f8c01d/ffffff?text=家居"/>
<span>
生活小课堂
</span>
<span class="card-time">
· 3小时
</span>
</div>
<div class="card-title">
为什么睡觉多的人身材1.8米的床,改选1.5米的呢?
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
187
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Stock Market Card -->
<div class="card card-small stock-card">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<span style="font-weight: bold;">
市场
</span>
<i class="fas fa-ellipsis-h">
</i>
</div>
<div class="stock-item">
<div class="stock-name">
上证指数
</div>
<div>
<div class="stock-price">
2,865.87
</div>
<div class="stock-change">
+1.01%
</div>
</div>
</div>
<div class="stock-item">
<div class="stock-name">
深证成指
</div>
<div>
<div class="stock-price">
8,929.50
</div>
<div class="stock-change">
+1.78%
</div>
</div>
</div>
<div class="stock-item">
<div class="stock-name">
创业板指
</div>
<div>
<div class="stock-price">
1,776.39
</div>
<div class="stock-change">
+2.63%
</div>
</div>
</div>
<div class="stock-item">
<div class="stock-name">
USD/CNY
</div>
<div>
<div class="stock-price">
7.1984
</div>
<div class="stock-change positive">
-0.00%
</div>
</div>
</div>
<div class="stock-item">
<div class="stock-name">
恒生指数
</div>
<div>
<div class="stock-price">
15,533.94
</div>
<div class="stock-change">
-1.18%
</div>
</div>
</div>
<div style="text-align: right; font-size: 12px; color: #0078d4; margin-top: 10px;">
查看更多
</div>
</div>
<!-- Sports Card -->
<div class="card card-small">
<img alt="冬季运动员在雪地上滑雪,展示了精彩的运动瞬间" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=冬季运动"/>
<div class="card-content">
<div class="card-source">
<img alt="体育频道图标" src="https://placehold.co/16x16/0078d4/ffffff?text=体育"/>
<span>
体育频道
</span>
<span class="card-time">
· 1小时
</span>
</div>
<div class="card-title">
退役韩国队组图揭秘,中国队摘铜,网友炸了!
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
2
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Game Character Card -->
<div class="card card-small">
<img alt="游戏角色特写,展示了一个白胡子老人的面部特写" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=游戏角色"/>
<div class="card-content">
<div class="card-source">
<img alt="一点资讯图标" src="https://placehold.co/16x16/e62117/ffffff?text=游戏"/>
<span>
一点资讯
</span>
<span class="card-time">
· 5小时
</span>
</div>
<div class="card-title">
《崩坏 2》无量仙人:好人还是坏人?深度剖析苏东坡色
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
976
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- American Airlines Card -->
<div class="card card-small">
<img alt="美国航空公司的飞机特写" class="card-image" src="https://placehold.co/400x200/767676/ffffff?text=美国航空"/>
<div class="card-content">
<div class="card-source">
<img alt="科技资讯图标" src="https://placehold.co/16x16/767676/ffffff?text=科技"/>
<span>
科技资讯
</span>
<span class="card-time">
· 17小时
</span>
</div>
<div class="card-title">
这还行吗?华为Pura 80 Ultra配置曝光,专属"黑科"停字
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
14
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Game Character Card -->
<div class="card card-small">
<img alt="游戏角色特写,展示了一个穿着华丽服装的女性角色" class="card-image" src="https://placehold.co/400x200/ff6700/ffffff?text=游戏角色"/>
<div class="card-content">
<div class="card-source">
<img alt="科技资讯图标" src="https://placehold.co/16x16/ff6700/ffffff?text=游戏"/>
<span>
科技资讯
</span>
<span class="card-time">
· 1天
</span>
</div>
<div class="card-title">
《王者荣耀》西施COS:身穿古装,头戴花饰,气质绝美还原
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
143
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- American Airlines Card -->
<div class="card card-small">
<img alt="一辆黑色轿车的侧面特写" class="card-image" src="https://placehold.co/400x200/000000/ffffff?text=汽车"/>
<div class="card-content">
<div class="card-source">
<img alt="汽车频道图标" src="https://placehold.co/16x16/e62117/ffffff?text=汽车"/>
<span>
汽车频道
</span>
<span class="card-time">
· 3天
</span>
</div>
<div class="card-title">
A、B、C、D级车是什么意思?这次总算明白了
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
212
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Earth Card -->
<div class="card card-small">
<img alt="地球从太空中拍摄的照片,展示了蓝色的海洋和白色的云层" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=地球"/>
<div class="card-content">
<div class="card-source">
<img alt="一点资讯图标" src="https://placehold.co/16x16/0078d4/ffffff?text=科学"/>
<span>
一点资讯/科学
</span>
<span class="card-time">
· 3天
</span>
</div>
<div class="card-title">
地球在宇宙的位置到底在哪里?我们是在中心还是边缘?
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
30
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Hospital Card -->
<div class="card card-small">
<img alt="医院走廊,展示了医院的内部环境" class="card-image" src="https://placehold.co/400x200/52c41a/ffffff?text=医院"/>
<div class="card-content">
<div class="card-source">
<img alt="健康大学堂图标" src="https://placehold.co/16x16/52c41a/ffffff?text=健康"/>
<span>
健康大学堂
</span>
</div>
<div class="card-title">
入住27天,我发现这家医院服务态度很好,纯粹是"没有硬骨头"
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
129
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- Game Ad Card -->
<div class="card card-small">
<img alt="游戏广告展示了一个可爱的卡通角色" class="card-image" src="https://placehold.co/400x200/e62117/ffffff?text=游戏广告"/>
<div class="card-content">
<div class="card-source">
<img alt="一点资讯图标" src="https://placehold.co/16x16/e62117/ffffff?text=游戏"/>
<span>
一点资讯
</span>
<span class="card-time">
· 21小时
</span>
</div>
<div class="card-title">
《崩坏2:魔道篇》进入全球票房前60,国外影院一票难求
</div>
</div>
<div class="card-actions">
<div class="card-action">
<i class="far fa-eye">
</i>
211
</div>
<div class="card-action">
<i class="far fa-heart">
</i>
</div>
</div>
</div>
<!-- American Airlines Card -->
<div class="card card-small">
<img alt="交通地图,展示了城市的道路和交通状况" class="card-image" src="https://placehold.co/400x200/0078d4/ffffff?text=交通地图"/>
<div class="traffic-map">
<div class="traffic-info">
<div class="traffic-time">
41
</div>
<div>
中等流量
</div>
<div>
昌平区 朝阳区
</div>
</div>
</div>
<div style="text-align: right; font-size: 12px; padding: 5px 10px;">
在地图上查看
</div>
</div>
<!-- Basketball League Card -->
<div class="card card-small">
<div style="padding: 10px; display: flex; justify-content: space-between; align-items: center;">
<span style="font-weight: bold;">
美国职业篮球联赛
</span>
<i class="fas fa-ellipsis-h">
</i>
</div>
<div style="padding: 0 10px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="display: flex; align-items: center;">
<img alt="篮球队标志" src="https://placehold.co/30x30/0078d4/ffffff?text=球队" style="width: 30px; height: 30px; margin-right: 10px;"/>
<div>
<div>
勇士
</div>
<div style="font-size: 10px; color: #999;">
西部
</div>
</div>
</div>
<div style="font-weight: bold; font-size: 18px;">
110 - 130
</div>
<div style="display: flex; align-items: center;">
<div style="text-align: right;">
<div>
湖人
</div>
<div style="font-size: 10px; color: #999;">
西部
</div>
</div>
<img alt="湖人队标志" src="https://placehold.co/30x30/552583/ffffff?text=湖人" style="width: 30px; height: 30px; margin-left: 10px;"/>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="display: flex; align-items: center;">
<img alt="凯尔特人队标志" src="https://placehold.co/30x30/007a33/ffffff?text=凯尔" style="width: 30px; height: 30px; margin-right: 10px;"/>
<div>
<div>
凯尔特人
</div>
<div style="font-size: 10px; color: #999;">
东部
</div>
</div>
</div>
<div style="font-weight: bold; font-size: 18px;">
118 - 123
</div>
<div style="display: flex; align-items: center;">
<div style="text-align: right;">
<div>
篮网
</div>
<div style="font-size: 10px; color: #999;">
东部
</div>
</div>
<img alt="篮网队标志" src="https://placehold.co/30x30/000000/ffffff?text=篮网" style="width: 30px; height: 30px; margin-left: 10px;"/>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; align-items: center;">
<img alt="火箭队标志" src="https://placehold.co/30x30/ce1141/ffffff?text=火箭" style="width: 30px; height: 30px; margin-right: 10px;"/>
<div>
<div>
火箭
</div>
<div style="font-size: 10px; color: #999;">
西部
</div>
</div>
</div>
<div style="font-weight: bold; font-size: 18px;">
122 - 105
</div>
<div style="display: flex; align-items: center;">
<div style="text-align: right;">
<div>
公牛
</div>
<div style="font-size: 10px; color: #999;">
东部
</div>
</div>
<img alt="公牛队标志" src="https://placehold.co/30x30/ce1141/ffffff?text=公牛" style="width: 30px; height: 30px; margin-left: 10px;"/>
</div>
</div>
</div>
<div style="text-align: center; font-size: 12px; color: #0078d4; padding: 10px; border-top: 1px solid #eee; margin-top: 10px;">
查看更多 美国职业篮球联赛
</div>
</div>
<!-- Calendar Card -->
<div class="card card-small calendar-card">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<span style="font-weight: bold;">
2025
</span>
<i class="fas fa-ellipsis-h">
</i>
</div>
<div class="calendar-header">
<div class="calendar-date">
2月9日 星期日
</div>
<div style="color: #ff6700;">
春节
</div>
</div>
<div style="font-size: 12px; color: #999; margin-bottom: 10px;">
农历正月初一
</div>
<div style="font-size: 12px; margin-bottom: 15px;">
春节,传统上是中国最重要的节日,是中国人民辞旧迎新的重要庆祝活动。
</div>
<div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
<div style="font-size: 12px; color: #999;">
日
</div>
<div style="font-size: 12px; color: #999;">
一
</div>
<div style="font-size: 12px; color: #999;">
二
</div>
<div style="font-size: 12px; color: #999;">
三
</div>
<div style="font-size: 12px; color: #999;">
四
</div>
<div style="font-size: 12px; color: #999;">
五
</div>
<div style="font-size: 12px; color: #999;">
六
</div>
</div>
<div class="calendar-grid">
<div class="calendar-day">
3
</div>
<div class="calendar-day">
4
</div>
<div class="calendar-day">
5
</div>
<div class="calendar-day">
6
</div>
<div class="calendar-day">
7
</div>
<div class="calendar-day">
8
</div>
<div class="calendar-day today">
9
</div>
</div>
<div style="text-align: center; font-size: 12px; color: #0078d4; margin-top: 15px;">
查看更多日历
</div>
</div>
</div>
</div>
</body>
</html>
我们可以看到相比GPT-4o,Claude还是可以还原出页面的整体布局结构,虽然不完美,但也在在努力尝试恢复出各个卡片的样式。相比GPT-4o,有明显的改进,但还是需要人工在后期做非常多的修改工作。
从以上的几个案例可以看到
- 基于多模态大模型的Design to code方案,可以实用简单的prompt来实现转换工作,相比基于规则、CV的方法,基于大模型的转换方案,使得程序员的开发工作变得异常简单。
- 在简单的UI设计稿转换上,大模型都表现相当优秀,Claude的还原精度可以用经验来形容。
- 对于复杂的UI,大模型的表现普遍不佳,但Claude的优势非常明显,比较接近可以实用的效果。对于复杂的UI,可以尝试先进行切分,将相对简单的UI组件输入给大模型,生成网页代码后,再由人工来进行合并。
参考文献
[1] Tony Beltramelli. pix2code: Generating code from a graphical user interface screenshot. In
Proceedings of the ACM SIGCHI Symposium on Engineering Interactive Computing Systems,
EICS 2018, Paris, France, June 19-22, 2018, pages 3:1–3:6. ACM, 2018. doi: 10.1145/3220134.
3220135.
[2] Hugo Laurenccon, L’eo Tronchon, and Victor Sanh. Unlocking the conversion of web screenshots
into html code with the websight dataset. 2024.
[3] screenshot to code project