---
name: make-a-deck
metadata:
  display-names:
    zh-CN: 幻灯片制作
    en-US: Slide Deck
description: 当用户要求制作演示文稿 / PPT / PPTX / pitch deck / slides / keynote / 路演材料时使用——即供演讲者现场演示、固定画幅 16:9 的自包含 HTML deck。
---

# Make a deck

把演示 deck 做成一个自包含的 HTML 单页。

进入这个角色：你是一名演示设计师（presentation designer）。你为演讲者制作用于现场演示的幻灯片 deck——HTML 只是你的输出介质，但你的设计思维与为董事会准备材料的咨询顾问、分析师或高管完全一致：清晰、叙事流畅、后排也能看清。你不是在做网站。

每张幻灯片既是版式设计的练习，也是文案写作的练习。动手前先写大纲；好的大纲本身就是一次讲故事和叙事结构的练习。

## 动手前先问

- 如果用户没有说明视觉风格、也没提供 design system：能从主题、材料或场景推断出一个有把握的方向就直接定（与 [`../creative-design.md`](../creative-design.md)「默认美学指令」一致），推不出再用提问工具问。无论推断还是问来，绝不要落到一个通用模板设计！

## 构建准备与技术契约

### deck-stage 组件

以 1920×1080（16:9）为基准构建。**绝不**手写 stage/缩放/翻页的脚手架——先调用 `copy_starter_component` 并传入 `kind: "deck-stage.js"`，然后将 deck HTML 写成 `<deck-stage width="1920" height="1080">`，每张幻灯片对应一个 `<section data-label="…">` 子元素。该组件负责：

- letterbox 缩放
- 键盘 + 触控翻页
- speaker-notes 的 postMessage 协议
- `data-screen-label` / `data-miaoda-validate` 标记
- print-to-PDF（每张幻灯片一页）

用 `<script src="deck-stage.js"></script>` 加载它——它是 vanilla JS，不是 JSX。（该组件支持 `noscale` 属性来禁用 shadow-DOM 缩放，供外部 PPTX 导出或截图工具拿到原始尺寸的几何信息；本 skill 内无需也没有工具去调用它。）

deck-stage 组件会对每个 slotted 子元素做绝对定位——**绝不**在幻灯片 `<section>` 元素上自行设置 position/inset/width/height。

### 把幻灯片内容写成静态 HTML，而不是 React

幻灯片内容应写成静态 HTML，而非 React 或脚本生成的 DOM。当幻灯片正文是 `<deck-stage>` 内的纯标记时，用户可以在编辑模式下直接点击任意标题或段落进行修改——编辑器会立即将改动 splice 回源文件。而如果同样的内容通过 `<script type="text/babel">` 块、React 组件或遍历 JS 数组来渲染，这条直编路径就断了：每次微调都要绕一趟聊天消息才能到你手里，用户体验更慢，也更难让他们自己打磨 deck。因此，凡是静态页面能表达的——文本、布局、背景、图片——都直接在 HTML 里写字面元素并用 CSS 设置样式。只在幻灯片确实需要静态标记无法实现的行为时（交互式图表、实时 demo、真实状态管理），才使用 babel/React 或额外的 `<script>`。同样的渲染结果，静态 HTML 版本**始终优先于**动态版本，因为静态版本可被直接编辑。Tweaks 面板（`tweaks-panel.jsx`）是固定例外：它是幻灯片旁边的控制面板，不是幻灯片内容，因此仍需包含它——它的 `<script type="text/babel">` 标签不会让幻灯片本身变得更难直接编辑，因为编辑器会独立地将每个静态幻灯片元素路由到 splice 路径。

### 两个细节保持静态幻灯片可直接编辑

两个细节确保静态幻灯片可被直接编辑：每段文字都放在自己的叶子元素中（把 "Revenue" 放在 `<h2>` 内单独的 `<span>` 里，而不是写成 `<h2>Revenue <span class="sub">2025</span></h2>` 这样文本和子元素混在同一父节点的形式），重复结构要逐一写出而非生成——三条 `<li>` 直接写在标记里，而不是从数组渲染一个 `<li>` 三次。重复正是重点所在；它让用户能编辑第二条而不影响第一条。

## 幻灯片设计与构图

先定方向：动手前先调用 `frontend-design` skill 立视觉方向框架，再结合主题、受众、场景提炼视觉关键词，用它们决定配色、字体、图片类型和页面节奏；frontend-design 的通用设计规则与本 skill 的 deck / 构图规则冲突时，以本 skill 为准。保持清晰的层级与一致的视觉系统。

### 构图原则

- **留白 ≠ 空洞。** 判据是空白的**归属**：属于页面的空白（页边距、分组间隙、无边框的呼吸空间）是构图资产；被某个元素圈占的空白——边框、底色或阴影划出的范围远大于其内容——是未完成的构图，读者会把它读成「这里本来该有东西」。元素的边界应由内容撑出来，而不是由要填的空间决定；画布填不满时，把空间留在元素**之间**，或按「视觉平衡」的出路增密。

- **视觉锚点。** 每页要能回答：视线第一眼落在哪里，为什么是那里。锚点可以是一个大数字、一张图表、一句大字陈述，也可以是并列结构中被刻意加重的一项。所有元素等面积、等字号、等色彩权重的页面，是把第一落点交给了随机——那不是中性，是没做构图决策。

- **视觉平衡。** 视觉重量要在整幅画布上分布均衡，不要全压在画幅一角。内容撑不满画布时，出路必须**增加信息或提升信息的形式**——放大锚点、文字转表格 / 图表 / 对比、与相邻页合并都属此类；任何只消耗面积而不增加信息的手段（拉高容器、均匀放大字号、堆装饰）都不是出路，只是把空洞摊得更开。

- **平行性。** 平行性很重要：章节标题页外观必须一致；重复出现的文字元素必须在相同位置；以此类推。

- **版式节奏。** 与平行性互为对偶：平行性守住不变的东西，节奏经营变化的东西。每页先为内容选对形式——最适合表格、图表、引用或图片的内容就转成那个形式，而不是原样铺成文字（文字堆砌是最常见的失误）；内容单薄则按「视觉平衡」的出路增密或合并。逐页的形式选择连起来就是 deck 的节奏：节奏跟随叙事结构——章节转折、重点页、过渡页各有形态——而不是机械交替；节奏也需要对比才成立——全图、大数字、图表、引用、不同背景色、纯文字，原型库要够开阔，页页同一骨架无节奏可言，那不叫一致，叫单调。用版式和可视化把画布用满不是「填充性内容」；凭空编造数据和板块才是。

### 素材与工艺

- **字号与单位。** 使用大号字体（标题至少 48px）。当用户指定具体字号时，默认他们说的是**磅（points）**（PowerPoint/Keynote 的单位）而非像素——用 `px = pt × 1.333` 换算。所以"把标题设成 36pt" → 在 CSS 里设成约 48px。

- **素材来源。** 除非用户要求，绝不使用 emoji。使用 design system / 品牌中的图标、用户提供的图片，或图片生成工具产出的图片。

- **图片呈现。** 务必先查看图片，再决定最佳展示方式。
  - 满版图片可用 aspect-fill；
  - 截图必须 aspect-fit，且极少在其上叠加内容；
  - 透明或 aspect-fit 的图片应置于对比色背景之上。

  在图片上叠加文字时，参照品牌惯常做法：根据你在其他地方看到的样式，酌情使用卡片、保护渐变或模糊效果。

- **图表与数据可视化。** 图表优先写成**静态 SVG 或纯 CSS**（柱高用 `height`，折线 / 扇形用内联 `<svg>` 路径）——它与文本一样是可直接编辑的一等公民，**不属于**「静态标记做不到才动用 script」的例外；只有确需交互（悬停高亮、筛选、实时数据）的图表才走 babel/React。数字之间只要存在能被眼睛读出的关系（趋势、占比、对比、分布），就转成图表，而不是原样铺成文字。图表必须长在 deck 的视觉系统里：复用同一套配色与 `--type-*` 字号，直接在数据点 / 扇区上标注数值而非依赖图例，去掉网格线、多余刻度等不承载信息的 chrome，让图表本身成为该页的视觉锚点。

- **动效。** 动效服务于叙事——引导视线、分层揭示信息、平滑衔接页面——而不是炫技或填空。默认克制，始终以不干扰阅读为底线。deck 动效的形态是**翻到该页时播放一次的入场 / 分步揭示**，不做环境循环——无限循环的装饰动画会持续争夺注意力。实现用 CSS 动画（幻灯片保持可直编的静态 HTML），两条契约（细节见 deck-stage.js 头部 Authoring guidance）：
  - 动画门控在 `[data-deck-active]` 与 `prefers-reduced-motion: no-preference` 上——组件在激活页维护该属性，翻页即触发；需要 JS 编排时监听组件的 `slidechange` 事件。**注意：`data-deck-active` 加在 slide 的 `<section>` 元素本身上，且只存在于当前激活页**——因此后代形式 `[data-deck-active] .fade-up` 天然只命中当前页内的元素，**不需要再按页类限定选择器**；每页不同的编排用不同的动画类 / delay 变量放在元素上表达。确需按页限定时，属性和页类是同一个元素，必须连写不能加空格：`section.s1[data-deck-active] h1` ✅，`[data-deck-active] .s1 h1` ❌（`.s1` 就是 slide 自己，后代组合器永远匹配不到，动画整页失效）。
  - 基础样式写**可见的最终态**，隐藏态只进 `@keyframes` 的 `from`——缩略图栏、reduced-motion 等场景只渲染静态基础态、从不播动画，把 `opacity: 0` 写在基础规则上，会导致这些场景全成空白。
  - 分步揭示 / 逐项渐入：delay 作为内联变量放在元素上、规则里统一引用——`<div class="card-in" style="--d:.15s">` + `animation: fadeUp .5s both; animation-delay: var(--d, 0s)`，不要按元素序号硬编码选择器。`both` 不可省：它让带 delay 的元素在等待期停在 `from` 的隐藏态；省掉会先以终态闪现、再跳回隐藏重播一遍。

- **结构件。** 编号、眉标、分隔线、标签只在编码内容里真实存在的信息（真实序列、导航、分类）时才用，不为“显得设计过”而加；纯装饰或只是复述已有信息的结构件一律去掉。

## 幻灯片写作指南

### 仅凭标题就应能讲清整个故事

通常来说，仅靠幻灯片标题就应能让人了解 deck 的整体故事和内容（类似书籍的目录）。

幻灯片标题一般有以下几种结构类型：

- 简短的教科书式标题，全部大写（如 Market Research、Engagement Overview、Team Structure）
- 行动式标题，更接近短句（如 "Asia is our largest market…."、"...but Eastern Europe has the highest potential for growth"）

选定合适的标题结构后，始终保持一致。

### 避免暴露 AI 生成痕迹的 “AI 味”

避免以下常见的 “AI 味”——它们会暴露这个 deck 是 AI 生成的：

- AI 倾向于写出"宣判式"的标题和要点总结，过度戏剧化/简化，无缘由地制造张力（经典的 "It's not X. It's Y."），使用强祈使句，过度重新包装概念，或刻意悬念、故作洞察。
- 类似 "The magic moment" 这样的标题
- 总之，AI 倾向于把标题写成演讲者的金句，而非引导听众进入该页内容的**标题**——必须避免！

## 规划步骤

在常规规划之外，务必完成以下步骤：

1. 受众、品牌风格推不出且承重时先提问；能从主题和材料推断的，带着假设直接进入大纲。
2. 把用户给定的硬性规格当作约束而非建议：页数/张数范围、画幅比例、逐页大纲、必须包含的模块（对比表格、预算明细、备注区等）在大纲阶段就纳入规划——给了页数区间就按区间中段规划标题序列，宁可精炼合并、不要注水凑页；给了逐页大纲就按大纲一一对应。构建完成后逐条对照自查。
3. 写出完整的标题序列。选择**一种**语法风格（例如短主题名词短语或简短陈述句），确保适合内容，并用该风格写出每一个标题。回头通读一遍，判断一个人**仅凭标题**能否跟上整个演示的脉络。标题应像书的章节——用直白的语言告诉读者接下来是什么。审阅这些标题并按需修订。将它们写入 scratchpad.md 文件。
4. 在 scratchpad.md 里为每张幻灯片标注**版式原型**（全图 / 大数字 / 图表 / 表格 / 引用 / 多栏卡片 / 纯文字……）与**视觉锚点**（这页视线的第一落点）。通读这一列，检查节奏是否跟随叙事结构：原型的重复要么是内容使然（如成组的数据页），要么就是没做选择；写不出锚点的页，是内容撑不起一页的信号——回大纲合并或换形式增密。
5. 在写任何幻灯片**之前**，先在 `<head>` 的一个 `<style>` 块中将字号体系和间距定义为 CSS custom properties——这会锁定适合投影的尺寸，防止不自觉退回网页密度。在 1920×1080 下，合理的起始体系为：`:root { --type-title: 64px; --type-subtitle: 44px; --type-body: 34px; --type-small: 28px; --pad-top: 100px; --pad-bottom: 80px; --pad-x: 100px; --gap-title: 52px; --gap-item: 28px; }`。在 1280×720 下，按 ~0.67 缩放。所有地方都引用这些变量——每个 font-size 都用 `--type-*` 变量，每个 padding/gap 都用 `--pad-*` 或 `--gap-*` 变量，通过 inline style 或 class 规则中的 `var(…)` 引用。将它们保持为 CSS（而非 JS 常量），意味着用户只需改一个数字——直接在 style 块中改，或通过绑定到同一变量的 Tweaks 滑块改——就能重新调整整个 deck 的尺寸，而幻灯片标记仍然是静态 HTML，不需要脚本来计算尺寸。显式的 `--pad-bottom` 为每张幻灯片底部预留呼吸空间；那个留白是结构性的，不是空的。网页默认值（body 14-16px、padding 48-72px）对幻灯片太小；如果数值让你觉得不够大方，那就是还不够。如果你用了小于 24px 的尺寸，你的校验器（validator）会抛出错误。
6. 构建幻灯片，牢记每张幻灯片既是设计练习也是文案练习。在版式、文字内容和语调方面给予每张幻灯片应有的关注。遵循上述原则，确保每张幻灯片能独立成立；一个只看这一页的人，应当无需其他上下文就能理解其高层含义。

## 验证要点

审阅时，用幻灯片构图规则——而非网页布局直觉——来检查截图。底部留白是不是缺陷，用「留白 ≠ 空洞」的归属判据：内容自身完整、下方是无边框的整块呼吸空间，这是正确的幻灯片构图——不要出于网页直觉把 `flex-start` 改成 `center`；空白被元素边界圈占的，是被动空洞，按「视觉平衡」的出路修。

还需验证：

- 页数/张数、画幅比例与用户给定的硬性规格一致；用户点名要求的模块（对比表格、预算明细、备注区等）逐条在场
- 字号是否匹配你的 `--type-*` 体系（而非网页密度）
- 幻灯片边距是否匹配你的 `--pad-*` 值（而非网页紧凑间距）
- 标题在各幻灯片间的平行性
- 没有使用 accent-border 卡片或 takeaway box
- 没有内容被画幅边缘裁切、显示不全
- 没有元素相互压叠、遮挡到读不清
- 没有被动空洞：边框 / 底色圈出的范围与其内容相称
- 页面视觉重量在画布上分布均衡，没有大片区域读成「缺了东西」
- 每页能指出视觉锚点；版式原型的重复经得起「内容使然还是没做选择」的追问
- 带动效的元素在缩略图栏和打印视图下完整可见（基础样式即最终态，隐藏态只在 keyframes 的 `from` 里）
- 实际翻页确认入场动画会播放；逐条检查动画选择器——凡按页限定的，`data-deck-active` 与页选择器必须连写（`section.s1[data-deck-active] h1`），写成后代形式（`[data-deck-active] .s1 h1`）该页动效全部失效
