# 把同一份內容分別做成 Marp 與 Reveal.js 簡報 — Markdown 投影片 vs HTML 框架

> 用 Marp 與 Reveal.js 各做一份相同的簡報並比較：原始檔可讀性（243 行 vs 287 行）、動畫、匯出格式，以及各自適合的場合。

- Source: https://oharu121.com/zh-tw/blog/marp-vs-revealjs-markdown-presentation-tools-comparison/
- Published: 2026-09-03T00:02:06+09:00
- Tags: Markdown, Node.js, 開發工具

---
## 引言

除了 PowerPoint 與 Google Slides 之外，還有一類可以當成程式碼來管理的投影片工具。其中兩個代表分別是從 Markdown 產生投影片的 **Marp**，以及以 HTML/JS 為基礎的簡報框架 **Reveal.js**。

為了判斷哪一個更適合自己的使用情境，我**用同一份內容分別在兩個工具上各做了一次**，再拿來比較。

## 前提與環境

- macOS（Apple Silicon）
- Node.js 22.x
- pnpm 11.x
- Marp CLI 4.4.0
- Reveal.js 5.1.0（透過 CDN）

## Marp 是什麼

Marp 是「Markdown Presentation Ecosystem」的縮寫，是一個從 Markdown 檔案產生簡報投影片的工具。

主要特徵：

- 用 Markdown 寫下的文字會直接成為投影片
- 以 `---`（水平線）分隔投影片
- CLI 可轉換為 HTML、PDF、PPTX 與 PNG
- VS Code 擴充套件支援即時預覽
- 主題與樣式在 frontmatter 中設定

## Reveal.js 是什麼

Reveal.js 是一個以 HTML、CSS 與 JavaScript 為基礎的簡報框架，也是 slides.com 背後的技術。

主要特徵：

- fragment 動畫（讓元素一個一個出現）
- 垂直投影片（逐層深入的結構）
- 透過 `data-auto-animate` 實現流暢的轉場
- 透過 `data-line-numbers` 做程式碼行高亮
- 外掛生態系（數學式、備忘稿、搜尋等）

## 安裝設定

### Marp

安裝 VS Code 擴充套件 `marp-team.marp-vscode` 之後，就能在編輯器裡即時預覽投影片。CLI 的安裝方式如下：

```bash
# 安裝 CLI
pnpm add -D @marp-team/marp-cli

# 建置投影片
pnpm dlx @marp-team/marp-cli slides.md -o slides.html

# 輸出 PDF
pnpm dlx @marp-team/marp-cli slides.md -o slides.pdf

# 輸出 PPTX
pnpm dlx @marp-team/marp-cli slides.md -o slides.pptx

# 輸出圖片（用於 LinkedIn／Instagram 輪播）
pnpm dlx @marp-team/marp-cli slides.md --images png
```

輸出格式會依副檔名自動判斷。輸出 PDF 需要 Chrome 或 Chromium；HTML 與 PPTX 則可直接使用。

### Reveal.js

```html
<!doctype html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/theme/black.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/monokai.css">
</head>
<body>
  <div class="reveal">
    <div class="slides">
      <section>Slide 1</section>
      <section>Slide 2</section>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/highlight.js"></script>
  <script>
    Reveal.initialize({
      hash: true,
      plugins: [RevealHighlight]
    });
  </script>
</body>
</html>
```

透過 CDN 就不需要安裝任何東西，一個 HTML 檔案即可獨立運作。若要裝在本機，使用 `pnpm add reveal.js`。

## 用兩個工具做出同一份內容

測試用的內容，我把自己先前寫過的一篇文章改成簡報，主題是 AI 程式撰寫 CLI 工具與 SSD 寫入量。裡面有程式碼區塊、表格、資料比較與敘事流程，正好能讓兩個工具擅長與不擅長的地方顯現出來。

這次做的示範已公開在這個 repo：

https://github.com/oharu121/marp-reveal-js-demo

### Marp 的原始檔（節錄）

```markdown
---
marp: true
theme: default
paginate: true
backgroundColor: #1a1a2e
color: #eee
style: |
  th { background: #e94560; color: white; }
  .columns { display: flex; gap: 2em; }
  .columns > div { flex: 1; }
---

<!-- _class: lead -->

# AI Coding CLIs Are Killing Your SSD?

---

## The Incident

> OpenAI's Codex CLI was found writing **640TB/year** to SSDs

- Trace-level logging to `~/.codex/logs_2.sqlite`
- **37TB** written in just 21 days

---

## Why This Matters

<div class="columns">
<div>

### Consumer SSD Lifespan

| SSD | TBW Rating |
|-----|-----------|
| Samsung 990 PRO 1TB | ~600 TBW |

</div>
<div>

### Codex Impact

- **640 TB/year** write rate
- Exceeds warranty in **< 1 year**

</div>
</div>
```

值得注意的地方：
- frontmatter 裡的 `style:` 區塊用來自訂 CSS
- `<!-- _class: lead -->` 套用標題投影片的版面
- `<div class="columns">` 做出兩欄版面（在 Markdown 裡嵌入 HTML）
- 表格、引用與程式碼區塊全都是標準 Markdown

### Reveal.js 的原始檔（節錄）

```html
<!-- fragment 動畫：元素一個一個出現 -->
<section data-auto-animate>
  <h2>Cross-Tool Comparison</h2>
  <table>
    <thead><tr><th>Tool</th><th>SSD Issue</th></tr></thead>
    <tbody>
      <tr class="fragment"><td>Codex CLI</td><td><span class="status-bad">Critical</span></td></tr>
      <tr class="fragment"><td>Claude Code</td><td><span class="status-warn">Past issues</span></td></tr>
      <tr class="fragment"><td>Gemini CLI</td><td><span class="status-ok">None</span></td></tr>
    </tbody>
  </table>
</section>

<!-- 垂直投影片：用向下鍵逐層深入 -->
<section>
  <section>
    <h2>Claude Code: Past Bugs</h2>
    <p><small>Press ↓ for each bug</small></p>
  </section>
  <section>
    <h3>Bug 1: Debug Log Infinite Loop</h3>
    <p class="fragment">Logger records ops taking >75ms</p>
    <p class="fragment">→ Debug file grows large</p>
    <p class="fragment">→ <span class="status-bad">42GB in 7 days</span></p>
  </section>
</section>

<!-- 程式碼行高亮：每次點擊移動焦點 -->
<section>
  <pre><code class="language-bash" data-line-numbers="1-2|4-5|7-12">
$ du -sh ~/.claude/debug
2.8M    ~/.claude/debug          # Normal

$ du -sh ~/.claude/file-history
12M     ~/.claude/file-history   # Normal

$ du -sh ~/.claude/*/  | sort -hr | head -5
866M    plugins/
434M    projects/
266M    security/
 12M    file-history/
2.8M    debug/
  </code></pre>
</section>
```

值得注意的地方：
- `class="fragment"` 讓元素一個一個出現
- 巢狀的 `<section>` 做出垂直投影片（逐層深入）
- `data-line-numbers="1-2|4-5|7-12"` 一步一步高亮程式碼行
- `data-auto-animate` 讓投影片之間的轉場變流暢
- `data-background-gradient` 為每張投影片換背景

## 比較結果

### 原始檔可讀性

Marp 的原始檔就是可以直接讀的 Markdown。無論在 GitHub 上預覽或用 VS Code 開啟，內容都很清楚。

```
# Marp 原始檔：243 行 Markdown
$ wc -l slides.md
243

# Reveal.js 原始檔：287 行 HTML
$ wc -l index.html
287
```

只看行數的話差別不大。但看這些行裝了什麼，結論就反過來了。先定義什麼叫「僅標籤的行」：整行都是 HTML 標籤，沒有別的內容。這樣算下來，Reveal.js 的 287 行裡**有 115 行、也就是 40% 只用來放標記**，Marp 則是 243 行裡的 19 行。扣掉標記與空行之後，**Marp 用更少的總行數承載了更多內容**：162 行對 152 行。

*Figure — SourceDensity: 從示範 repo 實測。僅標籤的行，指的是整行去掉空白後只剩標籤的行，例如 `</section>` 或 `<div class="columns">`。*

這就是為什麼 Marp 的原始檔本身就能當文件用，而 Reveal.js 的原始檔需要一個 HTML 解析器。

### 動畫與轉場

這是**最大的差距**。

Marp 的投影片內部沒有動畫功能，`---` 就只是切換投影片而已。

  逐張翻閱 Marp 簡報的樣子。每按一次，整張投影片就換成下一張，投影片內部什麼都不會動，比較表一開始就是完整的。

在 Reveal.js 裡：

- **fragment**：讓表格的行一次出現一列，把結論分階段揭露
- **垂直投影片**：保持主線流程，同時往下展開細節
- **程式碼行高亮**：`data-line-numbers="1-2|4-5"` 每次點擊都移動焦點
- **auto-animate**：元素在投影片之間流暢地移動

  同樣的內容在 Reveal.js 上。同一張比較表的行會隨著點擊一列一列出現，聽眾可以在下一列出現前先讀完每個工具的判定。

對技術影片（Fireship 風格的程式碼講解）以及研討會演講來說，這個差距是決定性的。

### 匯出

| 輸出格式 | Marp | Reveal.js |
|---------|------|-----------|
| HTML | 內建 | 內建 |
| PDF | 內建（需要 Chrome） | 需要另外的工具（decktape 之類） |
| PPTX | 內建 | 不支援 |
| PNG／JPG 圖片 | 內建（`--images`） | 不支援 |

當你需要把檔案交給使用 PowerPoint 的相關人員時，Marp 的 PPTX 輸出很方便。`--images png` 產生的圖片可以直接發成社群輪播貼文。

### 與 CI/CD 的相容性

Marp 可以很自然地組出 `md → html/pdf/pptx` 的 CLI 流程：

```bash
# 在 GitHub Actions 中自動建置投影片
pnpm dlx @marp-team/marp-cli slides.md -o dist/slides.html
```

Reveal.js 是靜態 HTML，所以完全不需要建置步驟，但要自動化 PDF 匯出就需要 headless 瀏覽器。

### 主題與樣式

Marp 可以用 frontmatter 裡的 `style:` 區塊來限定 CSS 的範圍。雖然有一些限制，但顏色、字型、表格樣式與背景這類基本的自訂完全做得到。

Reveal.js 讓你用上完整的 CSS 與 JS，所以沒有上限。CSS 變數（例如 `--r-heading-color`）讓主題很容易調整，複雜的版面也完全自由。

## 依使用情境選擇

### Marp 適合的場合

- **週會與 Sprint Review**：用 Markdown 快速寫、用 Git 管理、追蹤差異
- **把內部文件變成投影片**：在現有的 Markdown 文件裡加上 `---` 就成了一份簡報
- **LinkedIn 與 Instagram 的輪播貼文**：`--images png` 會把每張投影片輸出成圖片
- **CI/CD 中的自動建置**：能自然地放進 CLI 流程裡
- **團隊協作編輯**：Markdown 好審查，合併衝突也容易解決

### Reveal.js 適合的場合

- **研討會演講**：fragment 動畫與垂直投影片能控制聽眾的注意力落在哪裡
- **錄製技術影片**：一步一步的程式碼行高亮很適合 Fireship 風格的講解
- **互動式示範**：JS 外掛可以嵌入動態內容
- **需要精緻視覺呈現的場合**：背景漸層、自訂動畫

## 總結

| 面向 | Marp | Reveal.js |
|------|------|-----------|
| 撰寫速度 | 快 | 中等 |
| 原始檔可讀性 | 優秀（Markdown） | 低（HTML） |
| 動畫 | 沒有 | 豐富 |
| 程式碼高亮的控制 | 基本 | 可逐行推進 |
| 匯出 | HTML／PDF／PPTX／圖片 | HTML（其餘需要別的工具） |
| 與 Git 的相容性 | 優秀 | 可行，但差異不好讀 |
| 視覺自由度 | 中等 | 沒有限制 |

**結論是，這兩者並不互相競爭，而是用途不同。**

- **Marp＝日常的投影片**：把簡報當成文件的延伸。寫下來、納入版本控制，需要時再轉成 PPTX 或 PNG
- **Reveal.js＝關鍵的那場演講**：用動畫與互動把聽眾的體驗做出來

就我自己的感覺，日常工作有八成用 Marp 就綽綽有餘。它最大的優點是能以 Markdown 檔案的形式直接放進程式碼庫裡。於是簡報也成了一份產物，跟程式碼一起做版本控制。至於研討會演講與技術影片，呈現的精緻度會直接反映在成果上。那種場合就值得換成 Reveal.js。
