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

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

白色卡片上的黑色 Markdown 標誌,圓角矩形內含 M 與向下箭頭
本頁目錄

引言

除了 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 的安裝方式如下:

終端機視窗
# 安裝 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

<!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 的原始檔(節錄)

---
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 的原始檔(節錄)

<!-- 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 行。

兩份原始檔各把行數花在什麼地方以相同比例並排的兩條堆疊長條。Marp 的 slides.md 共 243 行:內容 162 行、僅標籤 19 行(8%)、空行 62 行。Reveal.js 的 index.html 共 287 行:內容 152 行、僅標籤 115 行(40%)、空行 20 行。Reveal.js 的總行數多了 44 行,但承載內容的行少了 10 行。內容僅標籤空行Marp — slides.md243 行16219 (8%)Reveal.js — index.html287 行152115 (40%)總行數更少,但承載內容的行反而更多。
從示範 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 風格的程式碼講解)以及研討會演講來說,這個差距是決定性的。

匯出

輸出格式MarpReveal.js
HTML內建內建
PDF內建(需要 Chrome)需要另外的工具(decktape 之類)
PPTX內建不支援
PNG/JPG 圖片內建(--images)不支援

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

與 CI/CD 的相容性

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

終端機視窗
# 在 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 外掛可以嵌入動態內容
  • 需要精緻視覺呈現的場合:背景漸層、自訂動畫

總結

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

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

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

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

分享這篇文章