关于 visualize
visualize 是面向 Claude Code 对话场景的技能,可将想法、数据或内容制作为单文件 HTML 可视化。它规定了主题切换、图表、响应式布局和无障碍等结构要求,并支持多种可选可视化库。
主要功能
- 01生成单文件 HTML 可视化
- 02浅色与深色主题切换
- 03支持图表和多种可视化库
- 04响应式布局与打印样式
- 05包含动画及无障碍要求
适用场景
- 01将对话中的想法转成可视内容
- 02把数据制作成图表或仪表板
- 03将文章或链接内容整理为可视页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ careerhackeralex/ visualize --skill visualize安装后在 Claude Code 中输入/visualize确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animations.mdanthropic-skill-guide-notes.mdcss-techniques.mddesign-system.mdeval.mdlibraries.mdmenu.mdskeleton.mdtypes.md详细介绍
可视化
将任意想法、数据或内容转化为令人惊艳的单文件 HTML 可视化作品。
创建文件后
写入 HTML 文件后,务必完成以下两项操作:
- 自动在浏览器中打开: 运行
open <filename>.html(macOS)或xdg-open <filename>.html(Linux),让用户立即查看 - 将文件路径作为可点击的 URL 返回: 在回复中包含
file://<absolute-path>,以便用户点击打开
创建后的回复示例:
Created your visualization! Opening in browser now...
📄 file:///Users/you/project/my-dashboard.html
关键要求(不可妥协)
⚠️ 缺少以下 8 项中的任何一项,都必定无法通过评估 ⚠️
每个文件都必须以 references/skeleton.md 中的骨架模板为基础——复制完整模板,然后添加内容。
- CSS 自定义属性: 必须使用以下确切名称:
--bg, --surface, --surface-hover, --border, --text, --text-secondary, --accent, --accent-secondary, --positive, --negative, --warning——不得使用其他名称(不能使用 --bg-primary 或 --text-primary)。关键: 评估系统兼容性要求使用这些确切的属性名称。 - 实用工具菜单系统(强制要求): 完整的
.viz-menu元素,其中包含.viz-menu-toggle按钮、.viz-menu-dropdown容器、下载 PNG 按钮(onclick="downloadImage()")、打印按钮(onclick="window.print()"),以及 html-to-image CDN 脚本(<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html-to-image.js"></script>)。评估关键项: 系统会自动检查菜单系统;如果缺失,将导致评估失败。 - 主题类(评估关键项): 必须在样式表中明确定义
.theme-light和.theme-dark两个类,并为它们完整定义自定义属性。必须采用以下示例:
:root { /* base properties */ }
.theme-light { --bg: #ffffff; --surface: #f8f9fa; --text: #1a1a1a; /* etc */ }
.theme-dark { --bg: #0a0a0a; --surface: #1a1a1a; --text: #ffffff; /* etc */ }
切勿仅依赖 :root 或 @media (prefers-color-scheme)——评估系统会检查基于类的主题。
4. 语义化 HTML: <main id="main-content"> 元素、强制要求:为主要内容区块(页眉、指标、图表等)使用多个 <section> 元素,以及跳转到内容的链接。每个不同的内容区域都必须用语义化的 <section> 标签包裹。
5. Chart.js 要求(评估关键项): 必须在结束 </head> 标签之前包含 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>。强制要求: 紧接在 Chart.js 脚本之后添加 <script>Chart.defaults.animation = false;</script>(用于防止动画故障,且评估系统会自动检查)。强制要求的图表校验: 每个图表函数都必须以 if (typeof Chart === 'undefined') { console.error('Chart.js not loaded'); return; } 开头。图表无障碍支持: 每个 canvas 元素都必须包含 role="img" 和描述性 aria-label 属性。关键图表配置: 为确保无障碍支持,设置 maintainAspectRatio: false、responsive: true 和 plugins: { tooltip: { enabled: true } }。切勿禁用工具提示——评估系统会检查工具提示是否已启用。图表可靠性系统: 使用专用的 ChartManager 模式,确保集成稳定可靠:
var ChartManager = {
charts: new Map(),
safeInit: function(canvasId, config) {
if (typeof Chart === 'undefined') {
console.error('Chart.js library not loaded - check CDN inclusion');
return null;
}
try {
if (this.charts.has(canvasId)) {
this.charts.get(canvasId).destroy();
this.charts.delete(canvasId);
}
var ctx = document.getElementById(canvasId);
if (!ctx) {
console.error('Canvas element not found: ' + canvasId);
return null;
}
// Ensure no conflicting chart instances
if (ctx.chart) {
ctx.chart.destroy();
delete ctx.chart;
}
// Set accessibility attributes
ctx.setAttribute('role', 'img');
if (!ctx.getAttribute('aria-label')) {
ctx.setAttribute('aria-label', 'Chart visualization');
}
// Initialize with enhanced error handling
var chart = new Chart(ctx, config);
this.charts.set(canvasId, chart);
return chart;
} catch (error) {
console.error('Chart initialization failed for ' + canvasId + ':', error);
return null;
}
},
updateTheme: function() {
if (typeof Chart === 'undefined') return;
this.charts.forEach(function(chart, canvasId) {
try {
chart.update();
} catch (error) {
console.error('Chart theme update failed for ' + canvasId + ':', error);
}
});
},
destroyAll: function() {
this.charts.forEach(function(chart) {
try {
chart.destroy();
} catch (error) {
console.error('Chart destruction failed:', error);
}
});
this.charts.clear();
}
};
使用 ChartManager.safeInit(),而不是直接使用 new Chart()。关键图表配置: 为确保无障碍支持,设置 maintainAspectRatio: false、responsive: true 和 plugins: { tooltip: { enabled: true } }。图表容器尺寸: 容器必须明确设置 height,且不小于 300px,才能确保图表正常渲染。使用基于主题的 CSS 自定义属性设置颜色,切勿使用静态十六进制颜色。切勿在 Chart.js CDN 中使用 import/export 语法——只能使用标准 var 声明。
CHART.JS 故障排查(关键): 如果图表显示为空白区域:
- 确认 Chart.js CDN 在
</head>之前引入 - 确认
Chart.defaults.animation = false;紧跟在 CDN 之后 - 确认图表初始化代码位于 DOMContentLoaded 事件侦听器中
- 确认文件中任何位置都没有模块导入/导出语法
- 确认正确使用了 ChartManager.safeInit() 模式
- 确认 canvas 具有
role="img"和aria-label属性
- 响应式设计: 区块间距 ≥48px,关键:视口宽度为 375px 时不得出现水平溢出(必须添加
@media (max-width: 375px) { body { overflow-x: hidden; } },以防止水平滚动),必须遵循字号层级: h1 ≥ 2.5rem,h2 ≥ 2rem,h3 ≥ 1.5rem,正文 = 1rem。幻灯片要求: 标题页 h1 ≥ 3rem,内容页标题 ≥ 2.5rem,标题层级之间要有清晰的视觉区分。幻灯片区块间距: 幻灯片中的主要区块间距必须 ≥48px(标题与内容、内容与图表、图表与导航之间)。在宽度为 375px 的视口下测试所有布局——仪表盘尤其容易出现图表容器溢出。 CSS 容器查询: 如需更高级的响应式设计,请使用基于容器的查询:
.chart-container { container-type: inline-size; }
@container (max-width: 400px) {
.chart-legend { display: none; }
.chart-title { font-size: 1rem; }
}
这能实现真正的组件级响应式效果,超越视口媒体查询的能力。
7. 打印与无障碍: 添加 @media print 样式,以及禁用动画的 @media (prefers-reduced-motion: reduce) 样式
8. 入场动画(必须): 必须通过 .animate 类、data-reveal 属性或 CSS @keyframes 添加入场动画。评估关键要求: 系统会自动检测动画是否存在,并将其视为必需项。
9. JavaScript 函数: cycleTheme()、toggleMenu(),顶层变量使用 var,而非 let/const
🔥 关键:原样复制 skeleton.md → 将 "YOUR CONTENT HERE" 替换为可视化内容 → 保存文件
核心原则
- 单文件 HTML —— 一个内联 CSS/JS 的
.html文件。可在任何浏览器中打开,离线运行,也易于通过电子邮件分享。 - 针对浅色主题优化 —— 现代设计优先保证浅色模式的质量。可通过切换启用深色主题。
- 默认即精美 —— 首次生成的内容无需任何迭代,就应具备专业的外观。
- 内容优先 —— 可视化服务于信息表达。切勿为了美观而牺牲清晰度。
- 响应式 —— 除非明确要求固定尺寸(例如 16:9 幻灯片),否则应适用于桌面、平板和移动设备。
- 视觉克制 —— 专业设计应避免增加杂乱感的装饰元素。不要使用漂浮的渐变球、彩虹边框或装饰性动画。
理念
HTML 不是“网站”,而是一种可视化工具。编写代码成本很低,每个人都应该能够轻松地将任何内容可视化。这项技能可以在几秒钟内将对话上下文、URL、文章、数据或原始想法转化为直观易懂的内容。
用户会在与 Claude Code 对话过程中调用这项技能。请充分利用完整的对话上下文——无论用户一直在讨论什么、分享了哪些链接或粘贴了哪些数据,都可作为素材。收到 URL 时,请抓取其内容并提取出可视化的信息。
输出规则
强制第一步:复制 references/skeleton.md 中的完整骨架,其中包含所有必需元素(菜单、主题系统、CSS 属性、语义化 HTML、无障碍功能)。切勿从头编写 HTML。
- 在
~/Downloads/(或用户指定的路径)中编写一个.html文件 - 文件名:使用描述性的 kebab-case 格式,例如
q4-revenue-dashboard.html、team-roadmap-deck.html - 以 skeleton.md 模板开头,将内容添加到 `` 部分
- 所有自定义样式都放在骨架基础样式之后的
<style>中 - 建议使用 CDN 库——根据任务选用最佳工具:
- Tailwind CSS —
https://cdn.tailwindcss.com(实用优先的样式,可自由使用) - Chart.js —
https://cdn.jsdelivr.net/npm/chart.js(柱状图、折线图、饼图、雷达图、圆环图) - D3.js —
https://cdn.jsdelivr.net/npm/d3@7(复杂/自定义数据可视化、力导向图) - Mermaid —
https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js(流程图、时序图) - Three.js — 适用于 3D 的场景
- Reveal.js — 需要时使用功能齐全的幻灯片引擎。**关键:**必须设置
html, body { height: 100%; overflow: hidden; },并将.reveal容器的height设为100%。配置必须使用数值尺寸:Reveal.initialize({ width: 1280, height: 720, center: true, controls: false })——切勿使用'100%'这样的字符串百分比,否则会导致视口高度为零、幻灯片空白。强制要求:禁用 Reveal.js 默认控件(controls: false)——默认的<>箭头叠层效果很差。请改为添加简洁的自定义底部导航栏:
- Tailwind CSS —
<nav class="slide-nav" aria-label="Slide navigation">
<button onclick="prevSlide()" aria-label="Previous slide">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg>
</button>
<span class="slide-counter" id="slideCounter">1 / 8</span>
<button onclick="nextSlide()" aria-label="Next slide">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
</button>
</nav>
.slide-nav { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; z-index: 9998; }
.slide-nav button { width: 28px; height: 28px; border-radius: 6px; background: transparent; border: none; color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; opacity: 0.3; transition: opacity 0.2s; }
.slide-nav button:hover { opacity: 0.7; }
.slide-counter { font-size: 12px; color: var(--text-secondary); font-weight: 400; min-width: 40px; text-align: center; opacity: 0.35; }
- Leaflet — 适用于地图和地理空间数据(
https://unpkg.com/[email protected]/dist/leaflet.js+ CSS)。**地理数据必需使用:**切勿手绘 SVG 大洲形状。使用 OpenStreetMap 瓦片或简洁的瓦片服务提供方。 - 图标和简单图形使用 SVG——除非用户提供,否则切勿使用外部图片 URL
- 尽可能优先使用 CSS 动画,而非 JS
详细的 CDN 链接、模式和技巧请参见 references/libraries.md。
设计系统
应用以下默认设置。这些设置经过精心制定和测试——只有用户提出要求时才覆盖。
**完整设计系统参考:**请参见 references/design-system.md,了解完整的字体、颜色、间距、动画、无障碍和视觉润色规范。
主要要点(完整详情请查阅参考文档):
设计说明
主题系统(关键):
- 仅使用基于 class 的主题——
<html class="theme-dark">或<html class="theme-light"> - 主题切换通过更改 html class 实现:
document.documentElement.className = 'theme-' + newTheme - 切勿使用
data-theme属性——评估系统要求使用基于 class 的主题 - 必需的 CSS 自定义属性:
--bg, --surface, --text, --accent, --border(评估兼容性的最低要求)
字体排版:
- 必须使用 Inter 字体——
https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap - **强制字体粗细层级:**h1 ≥ 700,h2 ≥ 600,h3 ≥ 500,正文 = 400(评估关键要求)
- 标题字距设为 -0.03em
- **韩文排版规范:**对于韩文内容,正文使用 Noto Sans KR,UI 元素使用 Inter。韩文行高设为
1.6(拉丁文字为 1.4)。韩文 Medium 字重对应西文 Regular(400)。请包含:https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;600;700&display=swap颜色: - 仅使用基于类的主题(禁止使用 @media prefers-color-scheme)
- 深色:背景 #0A0A0A,文字 #EDEDED。浅色:背景 #FAFAF9,文字 #0f172a
- 完整调色板请参阅参考。
- **卡片:**圆角 8px,仅在悬停时显示阴影(不使用 translateY/scale),边框为 1px solid var(--border)。**玻璃拟态升级:**对于高端布局,使用玻璃容器,设置
backdrop-filter: blur(8px)、半透明背景(使用 CSS 变量--glass-opacity: 0.08)和增强阴影。仅在首屏区域或主要卡片中选择性应用,以打造精致的层次感。 - **动画:**使用 CSS @keyframes 实现页面加载动画(.animate + .delay-N),使用 data-reveal + IntersectionObserver 实现滚动动画,使用 data-count 实现计数器动画。默认显示内容。首屏内容绝不可使用 data-reveal——应改用
.animate类。谨慎使用data-reveal(最多 3-4 个区块),且仅用于首屏以下的内容。 - **无障碍:**跳转到内容的链接、aria-label、地标角色、:focus-visible,以及用于图表数据的 sr-only。完整检查清单请参阅参考。
- **图标:**仅使用内联 SVG,禁止使用表情符号。采用 Lucide 风格,尺寸为 24x24,基于描边。
- **Chart.js(强制模式):**在脚本顶部设置
Chart.defaults.animation = false;,切换主题时销毁并重新创建图表,明确指定 rgba() 颜色,始终启用工具提示,在所有图表选项中设置maintainAspectRatio: false。无障碍:使用带有role="img"和描述性aria-label的 div 包裹 canvas。 **保护模式:**使用chartsBuilt标记——onThemeChange()必须在重建前检查if (chartsBuilt)。图表容器的最小高度需为 360px,以确保足够的视觉占比。 - **Chart.js 自定义样式:**在默认样式基础上应用专业样式——自定义内边距(
layout: { padding: 30 })、减少多余网格线(不透明度 ≤ 0.04)、使用圆角(borderRadius: 4),并选择与主题相配的配色。图表容器需要 12px 圆角、40px 内边距和 360px 最小高度,以确保足够的视觉占比。避免使用看起来像自动生成的库默认样式。 - **字体层级:**必须采用字号递减层级:h1 > h2 > h3 > 正文。**最低要求:**h1:≥3rem(48px),h2:≥2rem(32px),h3:≥1.5rem(24px),正文:1rem(16px)。**评估重点:**每个标题层级都必须明显小于上一级,相邻层级至少相差 0.5rem。有效层级示例:h1:3rem,h2:2.5rem,h3:1.5rem,正文:1rem。
- **视觉克制:**禁止使用浮动光球、渐变边框、标题渐变文字、缩放变换、发光效果和装饰性动画。
- **统计值颜色:**彩色数字必须具有语义含义(绿色/正值 = 良好指标,红色/负值 = 不良指标,强调色 = 主要/中性重点)。若没有明确的语义含义,则使用
var(--text)。禁止随意给统计值添加颜色。**对于包含 4 张或更多卡片的 KPI 网格:**数值最多使用 2 种强调色——最重要的单项指标使用var(--accent),其他所有指标使用var(--text)。仅将var(--positive)/var(--negative)用于变化指示器(箭头、百分比),不要用于卡片的主要数值。 - **背景氛围:**每个文件仅使用一种细微效果(径向渐变、噪点纹理或点阵网格)。背景氛围应与内容相适配——游戏仪表板应呈现出不同于财务报告的感觉。调整强调色和渐变色调,使其与主题内容相符。
- **AI 原生信息架构:**现代设计优先采用洞察驱动的层级。将最重要的指标/洞察置于首屏。采用渐进式呈现模式——立即展示关键数据,并通过悬停/点击提供深入查看。将上下文操作放在相关内容附近。先给出结论,再提供细节。
- **强制使用入场动画:**所有卡片/区块均使用 fadeInUp + stagger。
- **单屏海报:**在固定尺寸的 body 上使用 overflow:hidden + justify-content:space-between。9:16、1:1、4:5 尺寸请参阅参考。
关键实现要求
必须:使用骨架模板——完整的可复制 HTML 和所有内置要求,请参阅 references/skeleton.md。
JavaScript 实现规则:
- 所有顶层变量都必须使用
var(而不是let/const),以避免函数提升导致 TDZ 错误 - 主题切换必须使用
cycleTheme()函数——骨架模板内置了该函数,并提供正确的applyTheme()实现 - 菜单必须使用
toggleMenu()并处理点击外部区域的情况——骨架模板包含在点击外部区域和按下 Escape 键时自动关闭下拉菜单的功能 - **重建图表:**定义
function onThemeChange() {},以便在主题变化时重新渲染图表 - **移动端响应式:**在 375px 视口宽度下测试所有布局——卡片网格使用 CSS Grid
minmax(320px, 1fr)
评估检查器要求:
- 存在且可正常运行
cycleTheme()函数(可更改 html 类) - 存在
toggleMenu()函数,且可在点击外部区域时关闭菜单 - 顶层 JavaScript 变量使用
var声明 - 在 375px 宽度下没有水平溢出
- 除基本菜单外还包含交互元素(悬停状态、图表交互等)
骨架模板会自动提供所有必需功能。始终从 skeleton.md 开始,以避免实现错误。
语义化 HTML 要求
所有可视化内容都必须包含以下语义元素:
必需结构:
- 使用
<main>元素包含主要内容 - 使用
<section>元素划分主要内容块 - 地标角色(
role="banner"、role="main"、role="complementary")或“跳转到内容”链接 - 图表无障碍:在图表容器上设置
role="img"和aria-label
其他要求:
- 定义
@media print样式 - 定义
@media (prefers-reduced-motion)样式,以满足无障碍要求 - 各部分之间留出足够间距(≥48px)
- 为交互元素设置悬停状态
可视化类型
选择合适的格式。详细模式请参阅 references/types.md。
| 类型 | 适用场景 | 关键特点 |
|---|---|---|
| 幻灯片演示文稿 | 演示、提案 | 16:9、键盘导航、转场效果 |
| 信息图 | 数据摘要、可视化叙事 | 长页面滚动、大号数字、分区展示 |
| 仪表板 | 指标、KPI | 卡片网格 + 图表 |
| 流程图 | 流程、架构 | Mermaid 或 SVG 图表 |
| 时间线 | 按时间顺序排列的事件 | 左右交替、滚动触发 |
| 对比图 | 并列分析 | 特性矩阵、优缺点 |
| 数据可视化 | 图表、数据叙事 | Chart.js 或 D3 |
| 单页文档 | 摘要、简报 | 单视口、便于打印 |
| 思维导图 | 概念关系 | 径向 SVG 布局 |
| 看板 | 状态跟踪 | 基于列的卡片 |
| 轮播卡片 | 社交媒体(IG/LinkedIn) | 每张卡片 1080×1080,可滑动、大号文字 |
| 活动海报 | 会议、聚会、网络研讨会 | 竖版 A4/letter、大标题、日期/场地 |
| 简历/CV | 求职申请 | 单页、双栏、针对打印优化 |
| 横幅/页眉 | 邮件、博客、社交媒体封面 | 1200×630 或 1500×500,视觉背景上居中显示文字 |
| 引言卡片 | 社会认同、用户评价 | 竖版/方形、大号引言、署名 |
| 流程指南 | 操作指南、分步教程 | 编号步骤、图标、流程清晰 |
| 状态报告 | 高管进展汇报 | KPI + 进度条 + 要点,一页展示 |
| 组织结构图 | 团队结构 | 层级树、照片/头像、职位 |
| 数据故事 | 叙事 + 数据 | 滚动叙事,图表穿插于叙述文字中 |
| 产品卡片 | 功能亮点、产品发布 | 主视觉图片区域、功能标签、CTA |
轮播卡片规则
轮播卡片对社交媒体非常重要。请遵循以下规则:
- 正方形格式 —
1080×1080px(或通过 CSS var 配置) - 每张卡片表达一个观点 — 醒目的标题 + 最多 1-2 个辅助要点
- 滑动导航 — 箭头 + 圆点 + 触控滑动 + 键盘操作
- 卡片计数器 — 显示“3 / 8”
- 全部下载 — 将单张卡片或整组卡片导出为 PNG
- 以排版为主 — 标题字号为 2.5-4rem,正文尽量精简
- 颜色区分 — 每张卡片都可以有细微变化的强调色
- 打印布局 — 以网格形式展示所有卡片,方便打印
- 最多 10 张卡片 — 内容应聚焦
活动海报规则
- 纵向排版 — A4/letter 比例或正方形
- 视觉层级 — 活动名称(最大)→ 日期/时间 → 地点 → 描述 → CTA
- 醒目标题 — 3-5rem,最多 6 个词
- 突出日期/时间 — 设计成徽章或高亮区块
- 二维码区域 — 用占位框表示报名链接
- 优先考虑打印 — 深色或浅色主题打印效果都出色
引言卡片规则
- 大号引号 — 使用强调色装饰性地展示“ ”,并放大字号
- 引言文字 — 1.5-2.5rem,可使用衬线字体或斜体字重形成对比
- 署名 — 在引言下方标注姓名、职位、公司
- 正方形或纵向排版 — 针对社交分享优化
- 设计简洁 — 以引言为主角,其他元素保持低调
单屏 / 适配手机规则(海报、卡片、单页)
当用户要求内容适配“一个屏幕”“手机屏幕”“9:16”或“适配手机”时,应创建固定尺寸的单视口可视化内容,而不是可滚动页面。
尺寸:
- 9:16 纵向(手机):
width: 1080px; height: 1920px;— 标准 Instagram Story / 手机屏幕 - 1:1 正方形:
width: 1080px; height: 1080px;— Instagram 帖子 - 4:5 纵向:
width: 1080px; height: 1350px;— Instagram 纵向帖子 - 16:9 横向:
width: 1920px; height: 1080px;— 演示文稿幻灯片
关键 CSS 模式:
body {
width: 1080px; height: 1920px; /* or chosen ratio */
overflow: hidden; /* MUST — prevents scroll, enforces single screen */
display: flex; flex-direction: column; /* Flex column fills canvas completely */
}
.poster-header { padding: 44px 48px 0; }
.poster-grid { flex: 1; padding: 24px 48px 0; } /* flex:1 expands to fill remaining space */
.poster-footer { padding: 16px 48px 36px; }
布局规则:
- 在 body 上设置
overflow: hidden— 这是实现“单屏”的关键,不容妥协。 - 在主容器上设置
justify-content: space-between— 均匀分布各个区块,不留大片空隙。 - 在主要内容区域(网格、正文等)上使用
flex: 1,使其扩展并填满页眉和页脚之间的所有剩余空间。切勿使用会留下大片空白的固定height值。 - 将每个逻辑区块包裹在
<div>中,使 flexbox 能以区块为单位分配空间。 - 杜绝空白规则: 海报画布应 100% 得到利用。底部或两侧不能留有大片空白边距。如果存在明显空白,要么扩展内容填满空间,要么缩小内边距。内容应与画布完美契合。
- 在脑海中测试: 统计区块数量,将 1920px 分配给它们。每个区块约占 200-300px。如果内容稀疏,就放大元素(增大字号、增加内边距、放大图标)。
- 固定尺寸海报不要使用汉堡菜单 — 它会浪费空间,而且海报是为截图/导出而设计的,不用于交互。
9:16 的内容密度:
- 主视觉(标题 + 副标题):约占高度的 25%
- 2-3 个内容区块:约占高度的 55%
- 页脚/CTA:约占高度的 10%
- 留白(间距):约占高度的 10%
- 如果看起来空荡荡,说明内容太小。 放大字体、增加网格项目、使用更大的图标。
宽度为 1080px 的海报字体大小:
- 主视觉 h1:
68-80px(比网页上的更大 — 这是海报) - 区块标签:
15-18px,大写,字母间距为0.06em - 卡片文字:
16-20px - 正文:
20-24px
常见错误: 创建可滚动页面并对其截图。这不是海报,而是网页截图。海报是固定画布,每个像素都经过精心安排。
幻灯片规则
幻灯片是最常见的请求。请确保以下规则正确:
- 16:9 宽高比 —
100vw × 100vh,内容居中 - 响应式断点 — 使用
clamp()和容器查询,让幻灯片适配移动设备:.slide-container { container-type: inline-size; } .slide-title { font-size: clamp(2rem, 8vw, 4rem); } @container (width < 768px) { .slide-content { padding: 1rem; } } - 每张幻灯片只讲一个想法 — 如果还需要补充第二个想法,就另做一张幻灯片
- 每张幻灯片最多 40 个单词 — 超出时拆分内容或使用视觉元素
- 标题最多 6 个单词 — 简短有力、令人难忘
- 统计数据幻灯片采用大数字 + 小标签 — 数字设为 3-5rem,标签设为 0.875rem
- 键盘导航 — ← → 方向键、Space、Enter
- 触控导航 — 向左/向右滑动
- 点击导航 — 左侧三分之一 = 上一张,右侧三分之二 = 下一张
- 进度条 — 顶部的细渐变条,显示当前位置
- 幻灯片计数器 — 在底部导航中显示 "3 / 12"
- 突出移动端导航 — 确保移动设备上清晰显示导航控件。使用更大的触控区域(最小 44px)、对比鲜明的颜色,并为浮动导航添加 backdrop-blur
- 平滑过渡 — 使用
transform: translateX(),持续时间为 500ms,并采用 cubic-bezier - 入场动画 — 幻灯片中的元素依次延迟播放入场动画
- 演讲者备注 — 使用
data-notes属性,仅在打印时显示
高影响力演示幻灯片(商业场景)
适用于投资者演示、初创公司路演和高管简报:
- 强化主视觉幻灯片的视觉效果 — 使用更强烈的渐变、更大的字体(4-6rem),并醒目地展示引人注目的统计数据
- 清晰传达价值主张 — 主视觉幻灯片应在 5 秒内传达核心价值
- 彰显专业可信度 — 确保字体、间距和颜色选择符合企业级和投资级预期
- 用数据讲述故事 — 每张图表幻灯片都应明确标出洞察,而不只是展示原始数据
适配主题的幻灯片渐变(重要)
幻灯片在深色和浅色主题下必须呈现明显不同的视觉效果。渐变背景必须随主题变化:
/* Dark theme: deep, saturated gradients */
.theme-dark .slide-title { background: linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #1e3a5f 100%); }
.theme-dark .slide-content { background: var(--bg); }
/* Light theme: soft, pastel gradients */
.theme-light .slide-title { background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 50%, #dbeafe 100%); }
.theme-light .slide-content { background: var(--bg); }
规则:
- 标题/章节幻灯片:使用主题专属的渐变组合(深色主题 = 深沉且饱和,浅色主题 = 柔和且淡雅)。选择能体现内容主题的渐变颜色——科技路演使用冷蓝色,游戏路演使用鲜艳的紫色/青色,医疗演示文稿使用舒缓的绿色/蓝绿色。
- 内容幻灯片:使用
var(--bg)或var(--surface),不要使用硬编码的深色背景 - 幻灯片上的数据卡片:使用
var(--surface)和var(--border),它们会自动适配 - 不要在幻灯片内容中硬编码
#1a1a2e或类似的深色——请使用 CSS 变量 - 测试:切换主题,确保每张幻灯片在对应模式下都经过精心设计
幻灯片类型
- 标题 — 适配主题的渐变背景、大标题、副标题。居中对齐。
- 内容 — 标题 + 项目符号,或标题 + 视觉元素。避免文字过多。
- 章节分隔页 — 全出血强调色,仅显示章节标题。
- 统计数据 — 一个大数字、一个标签、一句洞察。
- 图表 — 使用 Chart.js 可视化,并附标题和关键结论。必须使用 chart-container 包装类。
- 双栏 — 拆分布局,用于对比或组合文字与视觉元素。
- 引言 — 大号引用内容,并注明出处。
- 结束页 — 行动号召、联系信息,或摘要 + 社交链接。
幻灯片图表要求(重要)
演示文稿中的图表幻灯片必须遵循与仪表板相同的容器标准:
<div class="chart-slide-container">
<h2>Chart Title</h2>
<div class="chart-container" style="height: 400px; padding: 40px; border-radius: 12px; background: var(--surface);">
<canvas id="slideChart" role="img" aria-label="Description"></canvas>
</div>
</div>
- 使用 chart-container 类 — 确保不同格式的评估标准一致
- 幻灯片图表的最小高度为 400px — 高于仪表板图表,以便在演示文稿中清晰阅读
- maintainAspectRatio: false — 正确适配幻灯片布局的必要设置
数据导入
用户提供数据时:
- CSV — 使用 JS 解析,自动检测表头,并渲染合适的图表类型
- JSON — 提取键作为标签、值作为数据,将嵌套对象作为数据系列
- 表格 — 转换为可视化对比图或图表
- 文本中的数字 — 提取并突出显示为统计卡片
- URL — 抓取内容、提取关键信息,并将其可视化为摘要
上下文感知
此技能用于对话进行期间。充分利用所有内容:
- 对话上下文 — 总结、整理或可视化已讨论的内容
- URL/链接 — 抓取并提取内容,然后进行可视化
- 粘贴的数据 — CSV、JSON、表格 → 图表、仪表板
- 想法/概念 — 将抽象讨论转化为可视化图表
- 代码/架构 — 可视化系统设计、数据流
始终使用真实内容。有真实上下文时,切勿生成占位数据。
特定类型的交互性(必须遵守)
每个文件都必须至少包含一种有意义的交互,主题切换和菜单除外。交互性不足的静态页面得分较低。
| 类型 | 必需的交互 |
|---|---|
| 速查表 | 搜索/筛选输入框 + 代码块的复制到剪贴板功能。使用 <details name="..."> 创建可折叠分组。 |
| 仪表板 | 筛选工具栏或指标下钻。至少提供日期范围或类别筛选器。 |
| 状态报告 | 可折叠的详情区域(使用 <details>)。进度条在滚动时进行动画展示。 |
| 引言卡片 | 自动轮播引言,或支持滑动的轮播。提供分享/复制按钮。 |
| 活动海报 | 带动画的倒计时(天/小时/分钟/秒)。提供 RSVP/注册按钮。 |
| 流程指南 | 将步骤设为互斥手风琴(<details name="steps">)。或者使用交互式进度跟踪器。 |
| 架构图 | 提供可点击节点,并显示弹出详情(使用 Popover API)。悬停时高亮关联项。 |
| 时间线 | 按时代/类别筛选。或者点击以展开事件详情。 |
| 对比 | 切换类别的显示/隐藏。或者逐行突出显示优胜项。 |
| 轮播 | 支持触屏滑动 + 键盘操作 + 自动前进选项。始终显示卡片计数。 |
| 幻灯片 | 已具备交互性(导航)。添加:演讲者计时器、幻灯片概览网格。 |
如果类型未列出,至少添加一种筛选、搜索、排序或展开/折叠交互。
布局变化(至关重要)
每个文件都必须呈现独特的设计,而不是只替换文字的模板。根据文件类型调整以下内容:
- 网格结构:混合使用 1 列、2 列和 3 列布局。使用 CSS Grid 的
span 2设置重点卡片。至关重要:务必在 768px 和 375px 屏幕宽度下进行测试,不得出现水平溢出。
移动优先的响应式模式(必须遵守):
.grid {
display: grid;
gap: 24px;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
@media (max-width: 768px) {
.grid { grid-template-columns: 1fr; gap: 16px; }
.container { padding: 24px 16px; }
}
@media (max-width: 375px) {
.card { padding: 16px; }
.stat-value { font-size: 2rem; }
}
- 区块节奏:交替使用全宽区块、卡片网格和单焦点区块。
- 内容密度:小尺寸下内容更丰富,比大尺寸下内容稀疏更显专业。包含 8 张 KPI 卡片 + 4 张图表的仪表板更真实;4 张 KPI 卡片 + 2 张图表则更像演示样例。
- 视觉焦点:每个文件都需要一个视觉主导元素(重点数据、关键图表、主要信息),而不是所有元素权重相同。
- 避免网格中出现落单项:网格项目数量为奇数且最后一行未填满时,为最后一个项目使用
grid-column: span 2,或调整grid-template-columns,避免最后一行只剩一张卡片。
反模式
- ❌ 大段文字 — 如果读起来像文档,那就不是可视化
- ❌ 字体过小 — 正文至少 14px,演示标题至少 20px
- ❌ 彩虹配色 — 使用调色板中的 2~3 种颜色,再搭配中性色
- ❌ 占位内容 — 切勿使用“Lorem ipsum”或虚假数据
- ❌ 过度设计 — 选择最简单且视觉效果出色的方案
- ❌ 布局拥挤 — 拿不准时,就增加留白
- ❌ 设计千篇一律 — 每种可视化都应有明确的设计意图,而不是套用模板
- ❌ 缺少菜单 — 每个输出都必须包含汉堡菜单
- ❌ 打印样式损坏 — 务必包含
@media print样式
高级技巧
仅在有助于提升效果时使用。代码片段请参阅 references/css-techniques.md。
- 玻璃拟态 — 使用
backdrop-blur-md bg-white/5 border border-white/10创建悬浮卡片 - 渐变文本 — 在主视觉标题中使用
background: linear-gradient(...); -webkit-background-clip: text - 滚动吸附 — 使用
scroll-snap-type: y mandatory作为替代幻灯片导航的方式(无需 JS) - 圆锥渐变 — 使用
conic-gradient()绘制纯 CSS 饼图/圆环图 - 数字动画 — 滚动时将计数器从 0 动画递增至目标值
- 弹簧缓动 — 使用
cubic-bezier(0.34, 1.56, 0.64, 1)实现活泼的微交互 - 动画过渡到 auto — 在
:root上设置interpolate-size: allow-keywords,即可实现平滑的height: auto过渡(Chrome 129+) - CSS 计数器 — 为分步骤流程自动编号
- View Transitions API — 实现平滑的主题切换动画
- 内联 SVG 图标 — 将简单图标绘制为
<svg>路径,无需图标库
强制使用的 HTML 骨架
每个可视化内容都必须从此骨架开始。 复制后再添加内容。
完整骨架代码: 完整的可复制 HTML 模板(包含主题、打印样式、Inter 字体、动画、菜单和悬停效果),请参阅 references/skeleton.md。
骨架提供:
- 基于类的深色/浅色主题(首次访问时检测 OS 设置,并通过 localStorage 持久保存)
- CSS @keyframes 动画(fadeInUp、fadeIn、slideInLeft、slideInRight)以及 .animate/.delay-N 类
- 通过 data-reveal 属性和 IntersectionObserver 实现滚动显示
- 通过 data-count 属性实现数字计数器
- 汉堡菜单,包含主题切换、PNG 下载(html-to-image)和打印/PDF 功能
- Popover 和 details 手风琴样式(Chrome 114+/120+)
- 使用 @page 边距框的打印样式
- 支持 prefers-reduced-motion
骨架规则
- 所有顶层 JS 变量都使用
var(避免 TDZ 错误) - 强制要求: 使用
data-reveal实现滚动动画,或使用.animate.delay-N实现页面加载入场动画。为.reveal类添加 JavaScript 滚动观察器。 - 定义
function onThemeChange() {},以便在切换主题时重新渲染图表 - 使用语义化 HTML:
<main>、<section>、<header>、<article> - 不要在脚本顶层使用
let/const
最小尺寸规则
元素必须足够大,确保清晰易读且具有足够的视觉分量:
- 时间线卡片: 最小宽度 280px,最小内边距 20px
- 时间线布局: 均匀分布时间线项目,避免出现大块空白。如果有 5 个项目,但只占用了 60% 的垂直空间,请添加更多内容区块(例如投资细分或影响指标),填满剩余的 40%。最后一个时间线项目下方绝不能留下大片空白。
- 图表容器: 最小宽度为父容器的 60%,最小高度为 300px(仪表板为 360px+)。在网格布局中,图表应使用
flex-grow: 1填满可用空间——300px 是下限,而非目标值。 - 统计数字: 最小字号为 2rem (32px),字重为 bold/extrabold
- 卡片内容区: 最小内边距 24px
- 区块间距: 强制要求主要区块之间至少间隔 48px——在区块元素上使用
margin-bottom: 48px或更大的值 - 幻灯片标题: 最小字号为 2rem (32px),最多 6 个词
- 正文: 最小字号为 1rem (16px),不得更小
如果内容看起来太小,那就确实太小。宁可做大一些。
文本可见性规则
文本必须始终清晰可见。 这是输出出错的首要原因。
- 深色主题:文本必须使用
var(--text),其值为#f9fafb(近白色) - 浅色主题:文本必须使用
var(--text),其值为#0f172a(近黑色) - 渐变背景上:添加
text-shadow: 0 1px 3px rgba(0,0,0,0.3),提升可读性 - 渐变/图片背景的主视觉幻灯片上:使用深色遮罩(
rgba(0,0,0,0.5)) - 绝不将文本颜色设置为与背景颜色接近的值
- 在心中测试:“这段文本在深色 (
#030712) 和浅色 (#f8fafc) 背景上都清晰可见吗?”
Chart.js 集成规则(关键 — 最常见的失败原因)
图表是第二常见的失败原因。以下规则对每个图表都必须遵守:
1. 容器结构(必需)
<div role="img" aria-label="Detailed description of chart data and insights">
<div class="chart-container" style="height: 360px; padding: 40px; border-radius: 12px; background: var(--surface);">
<canvas id="uniqueChartId"></canvas>
</div>
</div>
2. Canvas 尺寸(必需)
- **容器必须设置明确的高度:**仪表板至少为 360px,其他类型至少为 300px
- Canvas 元素无需设置尺寸——当
maintainAspectRatio: false时,Chart.js 会处理 - **容器内边距:**设置 40px 内边距,呈现专业的间距效果
- **容器圆角:**设置为 12px,呈现现代卡片外观
3. Chart.js 初始化(强制模式)
// REQUIRED: Chart destruction and canvas reset to prevent "Canvas already in use" errors
var chartsBuilt = false; // Guard flag
function buildCharts() {
if (chartsBuilt) return; // Prevent double-initialization during theme detection
// REQUIRED: Reset canvas before building
function resetCanvas(id) {
var old = document.getElementById(id);
if (!old) return null;
var parent = old.parentNode;
var canvas = document.createElement('canvas');
canvas.id = id;
parent.replaceChild(canvas, old);
return canvas;
}
// Example chart with required settings
var ctx = resetCanvas('myChart');
if (ctx) {
new Chart(ctx, {
type: 'bar',
data: { /* your data */ },
options: {
responsive: true,
maintainAspectRatio: false, // REQUIRED
animation: false, // MANDATORY: Plus set Chart.defaults.animation = false globally
plugins: {
tooltip: {
enabled: true, // NEVER disable tooltips
padding: 12,
cornerRadius: 8
}
},
layout: { padding: 20 } // REQUIRED: breathing room
}
});
}
chartsBuilt = true; // Mark as built
}
// CRITICAL: Disable Chart.js default animations IMMEDIATELY after Chart.js loads
Chart.defaults.animation = false; // MUST be set before any chart creation
// REQUIRED: Build charts after DOM loads
document.addEventListener('DOMContentLoaded', buildCharts);
// REQUIRED: Rebuild charts on theme change
function onThemeChange() {
chartsBuilt = false; // Reset flag
setTimeout(buildCharts, 100); // Slight delay for CSS variable updates
}
- 必须启用悬停工具提示——绝不要禁用 Chart.js 工具提示:
options: { plugins: { tooltip: { enabled: true, // NEVER set to false mode: 'index', intersect: false } } } - **图表最小高度:**桌面端为 300px,移动端为 250px
- **默认字体大小:**坐标轴刻度标签至少为 13px,坐标轴标题为 14px,图表标题至少为 16px。图例为 13px。
- **图表内边距:**添加
layout: { padding: { top: 20, right: 20, bottom: 20, left: 20 } },留出充足空间 - **坐标轴刻度配置:**设置
maxRotation: 0,让标签保持水平。如果标签超出空间,请使用maxTicksLimit减少数量 - **网格线:**颜色要非常淡——深色主题使用
rgba(255,255,255,0.04),浅色主题使用rgba(0,0,0,0.06) - **工具提示样式:**设置
padding: 12、cornerRadius: 8、titleFont: { size: 14 }、bodyFont: { size: 13 } - **数据点半径:**默认设为 0,悬停时设为 6——让折线图更简洁
- 设置
maintainAspectRatio: false,并通过 CSS 容器控制尺寸 - **使用适配主题的颜色:**在渲染时读取 CSS 变量,并在主题变更时重新渲染
- **图表文本颜色:**设置
Chart.defaults.color = getComputedStyle(root).getPropertyValue('--text-secondary').trim() - **网格线颜色:**使用
var(--border)的值 - **图例位置:**横向图表设为 'top',有足够空间的纵向图表设为 'right'
- **坐标轴标签:**尽可能保持水平——除非绝对必要,否则避免旋转
- **环形图/饼图:**始终在扇区上标注百分比
- 响应式:
responsive: true是默认值,但容器必须有明确的尺寸 - **高对比度颜色:**确保数据系列之间有足够的颜色差异,以满足无障碍要求
// Theme-aware Chart.js setup (include in every chart visualization)
function getChartColors() {
var s = getComputedStyle(document.documentElement);
return {
text: s.getPropertyValue('--text').trim(),
textSecondary: s.getPropertyValue('--text-secondary').trim(),
border: s.getPropertyValue('--border').trim(),
surface: s.getPropertyValue('--surface').trim(),
accent: s.getPropertyValue('--accent').trim(),
};
}
// REQUIRED: Reset canvas before rebuilding charts (prevents "Canvas already in use" errors)
function resetCanvas(id) {
var old = document.getElementById(id);
var parent = old.parentNode;
var canvas = document.createElement('canvas');
canvas.id = id;
parent.replaceChild(canvas, old);
return canvas;
}
// Usage in buildCharts():
// try { if (window.myChart) window.myChart.destroy(); } catch(e) {}
// window.myChart = new Chart(resetCanvas('myChart'), { ... });
// CRITICAL: Always check chart existence before destroy() to prevent console errors
function buildCharts() {
var isDark = document.documentElement.classList.contains('theme-dark');
var colors = getChartColors();
// Safe chart destruction and rebuild pattern
if (window.myChart) {
try { window.myChart.destroy(); } catch(e) { /* ignore */ }
}
window.myChart = new Chart(resetCanvas('myChart'), {
// chart config with theme-aware colors
options: {
scales: {
x: { ticks: { color: colors.textSecondary }, grid: { color: colors.border } },
y: { ticks: { color: colors.textSecondary }, grid: { color: colors.border } }
}
}
});
}
关键调试模式
计数器动画调试模式
如果 KPI 数值显示为“0%”而没有动画,请添加此调试模式:
// DEBUG: Add after counter observer setup to verify intersection
var counterEl = document.querySelector('[data-count]');
if (counterEl) {
console.log('Counter element found:', counterEl); // DEBUG
var cObs = new IntersectionObserver(function(entries) {
console.log('Counter intersection triggered:', entries); // DEBUG
entries.forEach(function(e) {
if (e.isIntersecting) {
console.log('Starting counter animation'); // DEBUG
animateCounters();
cObs.disconnect();
}
});
}, { threshold: 0.3 });
cObs.observe(counterEl);
} else {
console.warn('No [data-count] elements found'); // DEBUG
}
Chart.js 集成安全模式
所有 Chart.js 用法都必须遵循此模式,以防止控制台错误:
// STEP 1: Global variables - MUST use var, never let/const
var chartsBuilt = false;
// STEP 2: Chart building function with validation
function buildCharts() {
// CRITICAL: Always validate Chart.js loaded first
if (chartsBuilt || typeof Chart === 'undefined') return;
// STEP 3: Destroy existing charts to prevent "Canvas already in use"
if (window.myChart) window.myChart.destroy();
// STEP 4: Reset canvas elements
var canvas = document.getElementById('chartId');
if (!canvas) return;
// STEP 5: Get theme colors from CSS variables
var isDark = document.documentElement.className.includes('theme-dark');
var textColor = isDark ? '#EDEDED' : '#0f172a';
var gridColor = isDark ? 'rgba(255,255,255,0.04)' : 'rgba(0,0,0,0.06)';
// STEP 6: Create chart with proper options
try {
window.myChart = new Chart(canvas.getContext('2d'), {
// Your chart configuration here
options: {
responsive: true,
maintainAspectRatio: false, // REQUIRED
plugins: {
tooltip: { enabled: true }, // REQUIRED - never disable
legend: {
labels: { color: textColor, font: { family: 'Inter' } }
}
},
scales: {
x: {
ticks: { color: textColor },
grid: { color: gridColor }
},
y: {
ticks: { color: textColor },
grid: { color: gridColor }
}
}
}
});
chartsBuilt = true;
} catch (error) {
console.error('Chart creation failed:', error);
}
}
// STEP 7: Theme change handler
function onThemeChange() {
if (chartsBuilt) {
chartsBuilt = false;
buildCharts();
}
var ctx = document.getElementById('myChart');
if (!ctx) {
console.error('Chart canvas #myChart not found');
return;
}
// ... build chart
} catch (error) {
console.error('Chart building failed:', error);
}
}
修复菜单的外部点击行为
通过加强事件处理程序,确保点击菜单外部时菜单会关闭:
document.addEventListener('click', function(e) {
var menu = document.querySelector('.viz-menu');
var dropdown = document.getElementById('vizMenuDropdown');
if (!e.target.closest('.viz-menu') && dropdown) {
dropdown.classList.remove('open');
}
});
流程
- 理解 — 消息是什么?受众是谁?适合什么格式?
- 从骨架开始 — 复制上方的必需 HTML 骨架。绝不要从空白文件开始。
- 规划结构 — 在填充骨架之前,先列出内容和章节大纲
- 构建 — 添加内容、图表和样式。所有颜色都使用 CSS 变量。
- 验证清单:
-
html.theme-dark和html.theme-light基于类的主题选择器(不要使用 @media prefers-color-scheme)? - JS 是否在首次访问时检测操作系统偏好并将其存储在 localStorage 中?
- 所有文本是否都使用
var(--text)或var(--text-secondary)? -
@media print是否隐藏菜单并显示所有内容? - 是否包含
@media (prefers-reduced-motion: reduce)? - 是否包含带切换、主题、下载和打印功能的
.viz-menu? - 是否加载了正确的字体?(默认使用 Inter,韩语使用 Noto Sans KR 等)
- 非拉丁文字内容是否使用了合适的 CJK/RTL 字体?
- 是否通过
.animate类(CSS @keyframes)实现入场动画? - 滚动章节是否使用
data-reveal(即使没有 JS 也可见)? -
.card:hover是否具有变换效果? - 所有顶层 JS 变量是否都使用
var(而非let/const)? - 图表是否使用
var声明,并带有onThemeChange钩子? - 必须: 所有图表是否都用
role="img" aria-label="..."包裹? - 必须: 所有图表是否都启用了悬停工具提示(绝不可禁用)?
- 存在统计数据时,动画数字计数器是否使用
data-count? - 是否使用语义化 HTML:
<main>、<section>、<header>、<article>? - 所有图表是否都设置了明确的容器尺寸(高度 ≥300px)?
- 主视觉区/标题文本在两种主题下是否都清晰可见?
- 是否遵循最小尺寸规则(卡片至少 280px,文本至少 16px)?
- 加载时控制台是否没有任何错误?
-
质量标准:“好,就是好”,而不是“对 AI 生成的内容来说还不错”。