关于 stitch-html-components
将 Stitch 设计、本地 HTML 或 URL 转换为语义化 HTML5 和 CSS,无需框架或构建步骤。适用于跨平台页面、静态站点和移动 WebView,并采用移动优先样式及精简 JavaScript。
主要功能
- 01将 HTML 来源转为语义化 HTML5 和 CSS
- 02支持 Stitch、本地文件和 URL
- 03生成明暗模式 CSS 变量
- 04采用移动优先响应式样式
- 05将 JavaScript 限于基础交互
适用场景
- 01创建无框架的静态页面
- 02为移动 WebView 准备 HTML
- 03在选择框架前搭建原型
MCP 相关
处理 Stitch 来源时,技能会使用 Stitch MCP 工具发现工具命名空间并获取屏幕元数据,然后下载 HTML。本地文件和 URL 不需要 Stitch MCP。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gabelul/ stitch-kit --skill stitch-html-components安装后在 Claude Code 中输入/stitch-html-components确认已加载。
附带文件resources/architecture-checklist.mdscripts/fetch-stitch.sh
详细介绍
Stitch → HTML5 + CSS(平台无关)
你是一名专注于简洁、无依赖 HTML 和 CSS 的前端工程师。你可以将 HTML 源文件——Stitch 屏幕、本地文件或 URL——转换为带有 CSS 自定义属性的语义化 HTML5,无需 React、无需 Svelte,也无需构建步骤。输出可在任何环境中运行:桌面浏览器、移动浏览器、iOS WebView、Android WebView、Capacitor 应用和 Ionic 容器。
何时使用此技能
在以下情况下使用此技能:
- 用户需要平台无关的输出,例如“只要 HTML”“不要框架”“到处都能运行”
- 目标是在移动应用中使用 WebView(Capacitor、Ionic、Cordova)
- 构建静态网站或嵌入 CMS
- 用户尚未选择框架,想先做一个可运行的原型
- 在使用 Capacitor 封装为原生移动应用之前,先生成 HTML 基础结构
前提条件
一个 HTML 源文件。以下任意一种都可以:
- 一个 Stitch 屏幕——需要访问 Stitch MCP,并且已有生成的屏幕
- 一个 本地 HTML 文件——无需 Stitch 账号
- 一个 URL——无需 Stitch 账号
步骤 1:确定源文件
后续所有步骤都会读取同一个文件:temp/source.html。根据用户提供的内容,选择相应方式将 HTML 放到该文件中,然后继续执行步骤 2——无论标记来自哪里,本技能的其余部分都相同。
来自 Stitch 屏幕:
- 发现命名空间——使用
list_tools查找 Stitch MCP 前缀 - 获取元数据——使用
[prefix]:get_screen获取设计 JSON - 下载 HTML——GCS URL 需要使用可靠的下载器:
bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" - 视觉审查——改写前检查
screenshot.downloadUrl。在该 URL 后追加=s0以获取完整分辨率;无论 API 报告的width/height是多少,原始 URL 返回的都是 512px 缩略图。
来自本地 HTML 文件:
mkdir -p temp && cp "path/to/design.html" temp/source.html
来自 URL:
bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html"
尽管名称如此,该脚本是通用的强化型下载器——它会跟随重定向、重试暂时性失败、处理 gzip,并在结果为空时明确报错。无论 URL 是否指向 Stitch,它都能正常使用。
**来自屏幕截图:**没有上传方式——Stitch MCP API 没有图片上传工具。你可以通过 stitch-mcp-generate-screen-from-text 使用文本提示词重新创建设计,或手动编写 HTML,然后使用上面的本地文件方式。
只有 Stitch 方式需要 API 密钥。转换本地文件或 URL 完全不需要 Google 账号。
步骤 2:文件结构
output/
├── index.html ← Main page (or rename per screen)
├── css/
│ ├── tokens.css ← CSS custom properties (light + dark)
│ ├── base.css ← Reset, body defaults, typography
│ └── components.css ← Component styles
├── js/
│ └── main.js ← Minimal JS (theme toggle, mobile menu only)
└── assets/
└── images/
对于多屏幕项目,每个屏幕都使用单独的 HTML 文件。共享 CSS 放在 tokens.css 和 base.css 中。
步骤 3:CSS 自定义属性
将源文件中的颜色映射为语义化令牌。始终同时生成浅色和深色主题。按以下顺序解析十六进制值:
<head>中的内联tailwind.config(Stitch 生成的内容)——如果存在,直接使用。- 源文件中已有的 CSS 自定义属性(
:root { --color-primary: ... })——手写和模板化 HTML 中很常见。 - 外链或内联样式表——解析声明的颜色、字体系列、圆角和间距。
- 最后的办法——根据标记中出现频率最高的计算值推导令牌(主要背景色、文字颜色、强调色、标题/正文字体、圆角),并告知用户你的推断,以便他们进行修正。
URL 方式只会下载单个 HTML 响应——外链样式表可能不会一并下载。如果以上方式都无法确定某个令牌,请如实说明,不要自行编造配色方案。
/* css/tokens.css */
:root {
--color-background: [hex];
--color-surface: [hex];
--color-primary: [hex];
--color-primary-fg: [hex];
--color-text: [hex];
--color-text-muted: [hex];
--color-border: [hex];
--font-sans: [font-stack];
--font-mono: ui-monospace, monospace;
--radius-sm: [value];
--radius-md: [value];
--radius-lg: [value];
--shadow-sm: 0 1px 3px rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 12px rgb(0 0 0 / 0.1);
--transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Dark mode — system preference */
@media (prefers-color-scheme: dark) {
:root {
--color-background: [dark-hex];
--color-surface: [dark-hex];
--color-primary: [dark-adjusted-hex];
--color-primary-fg: [dark-hex];
--color-text: [dark-hex];
--color-text-muted: [dark-hex];
--color-border: [dark-hex];
}
}
/* Dark mode — manual toggle via data-theme="dark" on <html> */
[data-theme="dark"] {
--color-background: [dark-hex];
--color-surface: [dark-hex];
/* ... same values as above */
}
如果项目已有 design-tokens.css(来自 stitch-design-system),请导入它,而不是重新创建令牌。
步骤 4:基础 CSS
/* css/base.css */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
font-size: 16px;
/* Safe area insets for notched phones */
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
-webkit-text-size-adjust: 100%; /* Prevent font scaling on iOS rotation */
}
body {
font-family: var(--font-sans);
background-color: var(--color-background);
color: var(--color-text);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/* Skip link for accessibility */
.sr-only {
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip: rect(0,0,0,0); white-space: nowrap; border-width: 0;
}
.skip-link { /* ... see stitch-a11y skill */ }
/* Focus ring — keyboard only */
*:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
border-radius: 2px;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
步骤 5:语义化 HTML 结构
将 Stitch 布局转换为语义化 HTML5。只要有合适的语义元素,就绝不使用 <div>:
| Stitch 元素 | → HTML 元素 |
|---|---|
| 页面外壳 / 应用框架 | <body> → <header> + <main> + <footer> |
| 导航栏 | <nav aria-label="Main navigation"> |
| 主要内容区域 | <main id="main-content"> |
| 文章 / 帖子 / 卡片内容 | <article> |
| 侧边栏 | <aside> |
| 页面分区 | <section aria-labelledby="section-id"> |
| 按钮(无 href) | <button type="button"> |
| 带导航功能的链接 | <a href="..."> |
| 表单容器 | <form>,并为每个输入项添加 <label> |
| 图片 | <img alt="描述性文本"> |
移动端 HTML 模板:
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="theme-color" content="[--color-background hex]">
<title>[Screen title]</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="css/tokens.css">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/components.css">
</head>
<body>
<a href="#main-content" class="skip-link">Skip to content</a>
<div class="app-shell">
<header class="app-header" role="banner">
<nav aria-label="Main navigation">
</nav>
</header>
<main id="main-content" class="app-main">
</main>
<nav class="bottom-nav" aria-label="Tab navigation">
</nav>
</div>
<script src="js/main.js" type="module"></script>
</body>
</html>
步骤 6:移动端优先的 CSS 规则
每个组件都必须遵循以下移动端约束:
触控目标
/* All interactive elements: minimum 44×44px tap area */
button, a, [role="button"] {
min-height: 44px;
min-width: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
滚动
/* Smooth scroll on iOS */
.scrollable {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain; /* Prevent scroll chaining */
}
底部导航栏
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
/* Account for iOS home indicator */
padding-bottom: env(safe-area-inset-bottom);
background: var(--color-surface);
border-top: 1px solid var(--color-border);
display: flex;
justify-content: space-around;
z-index: 100;
}
/* Push main content above bottom nav */
.app-main {
padding-bottom: calc(60px + env(safe-area-inset-bottom));
}
响应式断点
/* Mobile-first: base styles are for mobile */
/* Tablet (768px+) */
@media (min-width: 768px) {
.container { max-width: 720px; margin: 0 auto; }
}
/* Desktop (1024px+) */
@media (min-width: 1024px) {
.container { max-width: 1200px; }
.bottom-nav { display: none; } /* Hide bottom nav, use sidebar */
.sidebar { display: block; } /* Show desktop sidebar */
}
步骤 7:精简 JavaScript
将 JS 减至最低限度。只有以下功能需要 JS:
- 主题切换(深色 / 浅色)
- 移动端菜单打开 / 关闭
- 手风琴 / 标签页的交互行为
// js/main.js
// Dark mode toggle
const html = document.documentElement;
const savedTheme = localStorage.getItem('theme') || 'light';
html.setAttribute('data-theme', savedTheme);
document.getElementById('theme-toggle')?.addEventListener('click', () => {
const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
});
// Mobile menu toggle
document.getElementById('menu-toggle')?.addEventListener('click', () => {
const nav = document.getElementById('mobile-nav');
const expanded = nav.getAttribute('aria-expanded') === 'true';
nav.setAttribute('aria-expanded', String(!expanded));
nav.classList.toggle('is-open');
});
步骤 8:Capacitor / WebView 说明
如果此 HTML 将嵌入 Capacitor 或 Ionic 应用:
- 所有资源路径都必须是相对路径(不能以
/开头):./css/tokens.css、./assets/logo.png - Capacitor 从
www/或dist/目录读取内容——请将输出放在那里 - Capacitor 的
capacitor.config.json设置 WebDir:"webDir": "www" - 如需调用原生 API(相机、文件系统),请使用 Capacitor 插件 JS API——这超出了本技能的范围
故障排除
| 问题 | 解决方法 |
|---|---|
| iOS 旋转屏幕后字体看起来放大了 | 在 html 中添加 -webkit-text-size-adjust: 100% |
| 内容被刘海遮挡 | 添加 env(safe-area-inset-*) 内边距 |
| iOS 上滚动感觉卡顿 | 添加 -webkit-overflow-scrolling: touch |
| 底部导航遮挡内容 | 为 <main> 添加 padding-bottom,其值等于导航栏高度加安全区内边距 |
| 移动端点击延迟(300ms) | 为按钮添加 touch-action: manipulation |
集成
- 先运行
stitch-design-system生成design-tokens.css——导入该文件,而不是重新创建设计令牌 - 之后运行
stitch-a11y,进行无障碍检查 - 运行
stitch-animate添加纯 CSS 过渡效果(大多数动画无需 JS)
参考资料
resources/mobile-template.html— 完整的移动端 HTML 样板resources/architecture-checklist.md— 发布前检查清单scripts/fetch-stitch.sh— 可靠的 GCS HTML 下载器