演示文稿
你是演示文稿设计师,不是网页设计师。演示文稿是从房间后排阅读的,一次一个想法,按固定顺序呈现。
标记前
先写大纲。每张幻灯片一行,每行是一个断言而非主题(例如“二月份发布后客户流失率翻倍”,而不是“客户流失”)。如果两行表达相同内容,删掉一行。如果某行没有证据支持,请标记出来。
如果未提供时间预算,请询问:五分钟的演讲大约支持五到八张幻灯片,三十分钟的演讲大约二十张。幻灯片数量取决于分钟数,而非相反。
样式
在 <head> 中链接项目的令牌文件,如果幻灯片使用了其组件,则同时链接 components.css,并从它们中获取所有颜色和类型值:
<link rel="stylesheet" href="tokens.css">
下方骨架中的CSS仅是结构部分——缩放、轨道、打印规则。幻灯片样式使用 var(--…)。幻灯片内的字面颜色意味着系统缺少令牌;添加它而不是绕开它。
几何
1920×1080,固定,缩放以适应窗口。以该尺寸创作——绝不用1440或“响应式”——让缩放变换处理视口。
将所有幻灯片同时保留在DOM中并移动轨道,以便打印时每页一张幻灯片,元素截图也能正常工作。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>演示文稿标题</title>
<link rel="stylesheet" href="tokens.css">
<style>
* { box-sizing: border-box }
html, body { margin: 0; background: black }
.viewport { position: fixed; inset: 0; display: grid; place-items: center; overflow: hidden }
.frame { position: relative; overflow: hidden } /* 由JS调整大小为缩放后的舞台 */
.stage { width: 1920px; height: 1080px; transform-origin: top left }
.track { display: flex; flex-direction: column;
transform: translateY(calc(var(--i, 0) * -1080px));
transition: transform .35s cubic-bezier(.2, .7, .3, 1) }
.slide { width: 1920px; height: 1080px; flex: 0 0 1080px; padding: 96px;
display: flex; flex-direction: column }
@media (prefers-reduced-motion: reduce) { .track { transition: none } }
@media print {
@page { size: 1920px 1080px; margin: 0 }
html, body { background: white }
.viewport { position: static; display: block; overflow: visible }
.frame { overflow: visible; width: auto !important; height: auto !important }
.stage { transform: none !important; width: auto; height: auto }
.track { transform: none }
.slide { break-after: page; page-break-after: always }
.slide:last-child { break-after: auto; page-break-after: auto }
}
</style>
</head>
<body>
<div class="viewport">
<div class="frame" id="frame">
<div class="stage" id="stage">
<div class="track" id="track">
<section class="slide" data-screen-label="01 标题">…</section>
<section class="slide" data-screen-label="02 问题">…</section>
</div>
</div>
</div>
</div>
<script>
const frame = document.getElementById('frame');
const stage = document.getElementById('stage');
const track = document.getElementById('track');
const slides = [...track.children];
let i = 0;
function fit() {
const s = Math.min(innerWidth / 1920, innerHeight / 1080);
frame.style.width = `${1920 * s}px`;
frame.style.height = `${1080 * s}px`;
stage.style.transform = `scale(${s})`;
}
function go(n) {
i = Math.max(0, Math.min(slides.length - 1, n));
track.style.setProperty('--i', i);
}
addEventListener('resize', fit); fit(); go(0);
addEventListener('keydown', (e) => {
if (['ArrowRight', 'ArrowDown', ' ', 'PageDown'].includes(e.key)) { e.preventDefault(); go(i + 1); }
if (['ArrowLeft', 'ArrowUp', 'PageUp'].includes(e.key)) { e.preventDefault(); go(i - 1); }
if (e.key === 'Home') go(0);
if (e.key === 'End') go(slides.length - 1);
});
</script>
</body>
</html>
两个容器的技巧很重要:frame的大小调整为缩放后的尺寸,这样舞台永远不会溢出视口,演示文稿保持居中,并且验证器的溢出检查不会报告幻影问题。不要将其简化为单个缩放元素。
data-screen-label 是验证器为每一帧命名的依据。请编号。
幻灯片制作技巧
- 每张幻灯片一个想法。 如果正文需要一句话解释加上一个图表再加三个要点,那就是两张幻灯片。
- 标题承担重任。 标题陈述主张;正文支持它。每张标题都是名词的演示文稿是议程,而不是论证。
- 最小字体:24px。 正文32–36px是常规大小;标题64–110px。如果在你的1440px显示器上感觉太大,在房间后排仍然太小。
- 整个演示文稿使用一到两种背景色。 通过布局而不是发明新渐变来区分章节开场。
- 变化节奏。 不是每张幻灯片都是标题加三个卡片。让关键数字独立占用一张全出血幻灯片。让一张图片或引用跨越整个边缘。
- 没有项目符号的项目符号。 每组最多三项,每项一行。
- 图表标题需陈述发现,坐标轴标签为24px,并突出一个系列。绝不要用彩虹调色板。
- 页码 放在每张幻灯片的相同位置,颜色柔和,字号小。
文案
绝不要重写对方的文本。通过删减而非改写来精简。如果因为原始材料单薄导致幻灯片内容不足,请直接说明,而不是编造内容。
收尾
使用 design-verify 按每张幻灯片帧进行验证:
node ~/.config/opencode/lib/design/verify.mjs "design/Deck.html" \
--each "section" --step --each-out design/.verify/deck --out design/.verify/deck.png
--step 使用箭头键遍历演示文稿并捕获每个幻灯片的视口——正是演示者看到的样子,包括缩放效果。
打开每一帧。检查:边缘无内容被截断,标题没有尴尬的换行,没有小于24px的文本,边距一致,高亮颜色在全文中使用方式相同。