Markdown 與 HTML 混合使用完全指南
Markdown 寫起來很舒服,但總會碰到它搞不定的排版需求——比如讓圖片置中、設定文字顏色、做個可摺疊的內容區域,或者用 HTML 表格實現跨行合併。這時候你可能會搜尋 "markdown in html" 或 "html in markdown",想知道這兩種格式能不能混著用。
答案是肯定的。Markdown 的設計者 John Gruber 在最初設計時就明確說過:HTML 是 Markdown 的發布格式,Markdown 不是 HTML 的替代品,而是它的補充。所以在 Markdown 檔案裡直接寫 HTML 標籤,不是什麼 hack,而是被官方鼓勵的做法。
不過這裡面有不少細節值得注意。比如,行內標籤和區塊級標籤的行為完全不同;有些平台支援 markdown="1" 屬性讓 HTML 標籤內部的 Markdown 語法也能生效,但有些平台完全忽略它。我在這篇文章裡會把這些規則和差異講清楚,並分享一些實際使用中的經驗。
核心規則:行內標籤 vs 區塊級標籤
理解 Markdown 和 HTML 混用的關鍵,在於搞清楚兩類 HTML 標籤在 Markdown 中的不同行為。
行內標籤(Inline Tags)—— 隨便用,Markdown 正常解析
行內標籤也叫 span-level 標籤,比如 <span>、<em>、<strong>、<a>、<code>、<br> 等。這些標籤可以在 Markdown 文字中任意位置使用,而且不影響周圍的 Markdown 語法解析。
這是一個 <span style="color:red">紅色文字</span> 的例子。
這行字裡 <em>這裡用 HTML 斜體</em> 而 **這裡用 Markdown 加粗**,兩者和平共處。
點擊 <a href="https://example.com" target="_blank">這個連結</a> 在新視窗開啟。上面的寫法在幾乎所有 Markdown 解析器中都能正常運作,因為行內標籤被當作 Markdown 文字的一部分來處理。
區塊級標籤(Block-level Tags)—— 內部 Markdown 會被忽略
區塊級標籤是另一回事。<div>、<table>、<p>、<pre>、<form> 這些標籤一旦出現,Markdown 解析器會認為這個區域不是 Markdown 了,裡面的內容直接按原始 HTML 處理。
下面這樣寫,**加粗** 不會生效:
<div>
這段話裡的 **加粗** 不會被渲染,*斜體* 也不會。
</div>這個行為是 Markdown 規範(包括原始規範和 CommonMark)的明確定義,不是某個解析器的 bug。Markdown 解析器在遇到區塊級 HTML 標籤時,會停止解析,直接把原始 HTML 原樣輸出。
我第一次碰到這個問題是在寫 GitHub README 的時候。當時想用 <div> 做一個兩列佈局,結果發現 div 裡面所有的 Markdown 連結和格式全部失效了,變成了一坨純文字。後來才知道,這是 Markdown 解析器的設計行為。
用空行隔開區塊級標籤和 Markdown 內容
有一個容易忽略的規則:區塊級 HTML 標籤的前後需要用空行與 Markdown 內容隔開。如果不隔開,有些解析器會把 HTML 標籤當作普通文字來處理。
<!-- 正確寫法:前後有空行 -->
前面的 Markdown 內容。
<div>
<p>HTML 區塊級內容</p>
</div>
後面的 Markdown 內容。另外,區塊級 HTML 標籤不要用空格或製表符縮排。如果縮排了 4 個空格或 1 個製表符,Markdown 會把它當成程式碼區塊來處理。
常見用法:用 HTML 補充 Markdown 做不到的事
既然 Markdown 支援嵌入 HTML,那具體有哪些場景會用到?這裡列幾個最常見的。
控制圖片大小和位置
Markdown 的圖片語法  沒有指定尺寸和對齊方式的選項。如果你想控制圖片的顯示大小或者讓它置中,就得用 HTML。
<!-- 設定圖片寬度 -->
<img src="image.png" width="300" alt="範例圖片">
<!-- 圖片置中 -->
<div align="center">
<img src="image.png" width="80%" alt="置中圖片">
</div>在 GitHub 上,<img> 標籤的 width 和 height 屬性是支援得比較好的。不過 align 屬性屬於舊式 HTML,有些平台可能會忽略,更現代的做法是用 CSS 的 style 屬性。
文字顏色和樣式
Markdown 沒有設定文字顏色的語法。你可以用 <span> 配合 style 來實現:
<span style="color: red;">紅色文字</span>
<span style="color: #0066cc; font-size: 18px;">藍色大字</span>
<span style="background-color: yellow;">黃底高亮</span>說實話,這種方式在純 Markdown 編輯器裡看著挺彆扭的,但渲染出來的效果確實能用。我的建議是,如果你只是偶爾需要改個顏色,用 <span> 就夠了;如果整個文件都需要複雜的樣式控制,那可能應該直接寫 HTML 而不是 Markdown。
可摺疊內容(details/summary)
<details> 和 <summary> 這兩個 HTML 標籤在 GitHub、GitLab、CSDN 等平台上支援得很好,可以做出可摺疊/展開的內容區域,非常適合放一些補充資訊或長程式碼區塊。
<details>
<summary>點擊展開查看詳細程式碼</summary>
```python
def hello():
print("Hello, World!")
注意 `<summary>` 標籤裡的文字會作為摺疊區域的標題顯示。這個技巧在做 README 文件時特別實用,把安裝步驟或常見問題摺疊起來,頁面看起來清爽很多。
### 鍵盤按鍵樣式
如果你在寫技術文件,可能需要展示鍵盤快捷鍵。`<kbd>` 標籤正好派上用場:
```markdown
按 <kbd>Ctrl</kbd> + <kbd>C</kbd> 複製,<kbd>Ctrl</kbd> + <kbd>V</kbd> 貼上。大多數 Markdown 渲染器會把 <kbd> 顯示為帶邊框的小方塊,看起來像真實的鍵盤按鍵。
頁內錨點跳轉
Markdown 的連結語法 [文字](#錨點) 支援頁內跳轉,但你需要先定義錨點位置。可以用 HTML 的 id 屬性來實現:
<div id="section-1"></div>
## 第一個章節
這裡是章節內容...
[跳轉到第一個章節](#section-1)在 GitHub 上,標題會自動生成錨點(基於標題文字),所以這個技巧主要用於非標題位置。
進階技巧:讓 HTML 標籤內部的 Markdown 也生效
前面說了,區塊級 HTML 標籤內部的 Markdown 語法預設不被解析。但有些場景確實需要在 HTML 標籤裡寫 Markdown,比如用 <div> 做佈局的同時還想用 Markdown 的連結和格式。
方案一:加空行(CommonMark 規範)
CommonMark 規範(GitHub、GitLab、很多現代解析器使用)支援一種方式:在 HTML 標籤和內容之間加空行,讓解析器知道裡面的內容應該當作 Markdown 來處理。
<div>
這段話裡的 **加粗** 會正常渲染。
- 列表項一
- 列表項二
</div>關鍵是開始標籤 <div> 後面、內容前面,以及內容後面、結束標籤 </div> 前面,都要有空行。我實測在 GitHub 上這個方式是生效的。
方案二:markdown 屬性(Python-Markdown、Markdown Extra)
Python-Markdown 的 md_in_html 擴展和 PHP Markdown Extra 支援在 HTML 標籤上添加 markdown 屬性,明確告訴解析器內部內容按 Markdown 處理。
<div markdown="1">
這裡的 **Markdown** 會正常渲染。
</div>markdown 屬性支援三種值:
| 值 | 效果 |
|---|---|
"1" | 使用標籤的預設行為(div 用 block 模式,p 用 span 模式) |
"block" | 強制區塊級模式,段落、標題、列表都會正常渲染 |
"span" | 強制行內模式,只渲染加粗、斜體、連結等行內語法 |
需要注意的是,這個屬性不是標準 Markdown 規範的一部分,只有在支援它的解析器上才能用。比如 GitHub 的渲染器就不支援這個屬性(至少目前不支援),但 GitHub Pages 的 Jekyll/Kramdown 環境是支援的。
方案三:用 <span> 替代 <div>
因為行內標籤內部的 Markdown 不受影響,一個取巧的辦法是用 <span> 代替 <div>,然後透過 CSS 讓它表現為區塊級元素。
<span style="display: block; border: 1px solid #ccc; padding: 10px;">
這段話裡的 **Markdown** 會正常渲染,因為 span 是行內標籤。
</span>這個方法相容性比較好,但語義上不夠嚴謹——<span> 語義上是行內元素,強制改成區塊級在無障礙性方面不太好。
平台相容性對比
不同平台對 Markdown 中 HTML 的支援程度差異很大。我根據實際測試和官方文件整理了下面的對比表。
| 功能 | GitHub | GitLab | Jekyll/Kramdown | Python-Markdown | Obsidian | Typora |
|---|---|---|---|---|---|---|
| 行內 HTML 標籤 | 支援 | 支援 | 支援 | 支援 | 支援 | 支援 |
| 區塊級 HTML 標籤 | 支援 | 支援 | 支援 | 支援 | 支援 | 支援 |
| 區塊級標籤內加空行解析 Markdown | 支援 | 支援 | 支援 | 不支援 | 不支援 | 部分支援 |
markdown="1" 屬性 | 不支援 | 不支援 | 支援 | 支援(需擴展) | 不支援 | 不支援 |
<details>/<summary> | 支援 | 支援 | 支援 | 支援 | 支援 | 支援 |
<img> 設定 width/height | 支援 | 支援 | 支援 | 支援 | 支援 | 支援 |
<span style="color:"> | 支援 | 支援 | 支援 | 支援 | 支援 | 支援 |
<iframe> | 不支援 | 不支援 | 支援 | 支援 | 部分支援 | 支援 |
<script> | 不支援 | 不支援 | 不支援 | 不支援 | 不支援 | 不支援 |
資料來源:各平台官方文件 + Stack Overflow 高讚回答 + 實際測試。GitHub 的 HTML 白名單可在 github/markup 專案中查看。
幾個值得注意的點:
- GitHub 出於安全考慮,對可用的 HTML 標籤有白名單限制。
<script>、<iframe>、<style>這些標籤會被直接過濾掉。 - Obsidian 內部使用自己的 Markdown 解析器,對 HTML 的支援有其特殊性。比如在 Obsidian 裡不能在 HTML 區塊中使用 Markdown 語法,但可以透過 DataviewJS 外掛間接實現。
- Jekyll 的 Kramdown 解析器對 HTML in Markdown 的支援是最全面的,
markdown="1"屬性和區塊級標籤內加空行兩種方式都支援。
實際應用場景與範例
場景一:GitHub README 中讓圖片置中
這是我在做開源專案時經常用的寫法:
<div align="center">

**一個簡潔的專案描述**
[](https://github.com/user/repo)
</div>在 GitHub 上,這個寫法能正常運作是因為 <div align="center"> 後面的空行讓解析器把內容當作 Markdown 來處理。順便說一句,<div align="center"> 雖然用了過時的 align 屬性,但在 GitHub 上這是最可靠的置中方式。
場景二:在 Markdown 中嵌入複雜表格
Markdown 表格不支援跨行跨列(rowspan/colspan)。當你需要這種效果時,可以直接用 HTML 表格:
<table>
<tr>
<th>功能</th>
<th>免費版</th>
<th>專業版</th>
</tr>
<tr>
<td rowspan="2">儲存空間</td>
<td>5GB</td>
<td>100GB</td>
</tr>
<tr>
<td colspan="2">可擴展至 1TB(僅專業版)</td>
</tr>
</table>場景三:用 CSS 實現多列佈局
在支援 style 屬性的平台上(比如自己的部落格或文件站),可以用 CSS 實現簡單的多列排版:
<div style="display: flex; gap: 20px;">
<div style="flex: 1;">
### 左列內容
- 要點一
- 要點二
</div>
<div style="flex: 1;">
### 右列內容
- 要點三
- 要點四
</div>
</div>不過這種寫法在 GitHub 上不一定生效,因為 GitHub 會過濾掉 style 屬性中的部分 CSS 規則。
常見問題
Markdown 文件中能直接寫 CSS 嗎?
可以,但支援程度有限。你可以用 <style> 標籤來定義樣式,不過很多平台(特別是 GitHub)會把它過濾掉。在自己的部落格或文件站上通常沒問題:
<style>
.custom-box {
border: 1px solid #ddd;
padding: 15px;
border-radius: 5px;
}
</style>
<div class="custom-box">
這段文字會有自訂的邊框和內邊距。
</div>為什麼我的 HTML 標籤在 GitHub 上不生效?
最常見的原因有兩個:一是 GitHub 有 HTML 白名單,<script>、<iframe>、<form> 等標籤會被直接移除;二是 GitHub 會過濾掉 style 屬性中的部分 CSS(比如 position、z-index 等可能影響頁面佈局的屬性)。如果你需要完全控制 HTML 和 CSS,建議使用 GitHub Pages 而不是直接在 README 中寫。
<font> 標籤還能用嗎?
技術上可以,但不推薦。<font> 在 HTML5 中已被棄用(deprecated),雖然瀏覽器仍然支援渲染。建議使用 <span style="color: red;"> 的方式來替代。
安全注意事項
在 Markdown 中嵌入 HTML 時,安全性是一個需要注意的方面,特別是在使用者可以提交 Markdown 內容的平台上。
XSS 風險
如果在 Markdown 中允許任意 HTML,就可能存在 XSS(跨站指令碼攻擊)的風險。比如:
<!-- 危險範例,不要在生產環境中使用 -->
<img src="x" onerror="alert('XSS')">
<a href="javascript:alert('XSS')">點擊我</a>大多數平台會過濾掉 onerror、onclick 這類事件屬性和 javascript: 協定的連結。但如果你自己在搭建 Markdown 渲染系統,需要確保使用 XSS 過濾庫(比如 DOMPurify)來清理 HTML 內容。
內容安全策略
如果你在用 Markdown 解析庫(如 marked.js、markdown-it)構建自己的應用,建議:
- 始終啟用 HTML sanitization(HTML 清理)選項
- 使用白名單而非黑名單來過濾 HTML 標籤和屬性
- 不要信任使用者提交的 Markdown 中的 HTML 內容
總結
Markdown 與 HTML 的混合使用並不複雜,記住幾個要點就夠了:
- 行內 HTML 標籤(
<span>、<em>、<a>等)可以在 Markdown 中隨意使用,不影響 Markdown 語法解析 - 區塊級 HTML 標籤(
<div>、<table>、<p>等)內部的 Markdown 語法預設不被解析 - 如果需要在區塊級標籤內使用 Markdown,可以嘗試加空行(CommonMark 規範)或
markdown="1"屬性(Python-Markdown / Kramdown 支援) - 不同平台的 HTML 支援程度差異很大,使用前最好先在目標平台上測試
- 安全性不能忽視,特別是在接受使用者提交的 Markdown 內容時
說到底,Markdown 和 HTML 不是對立的。Markdown 處理大部分寫作場景已經足夠好了,偶爾需要更精細的控制時就用 HTML 來補充。兩者配合使用,才是最實用的方式。
參考資料
- Markdown: Syntax - Daring Fireball — Markdown 官方語法說明
- CommonMark Spec — CommonMark 規範
- Markdown Guide - Basic Syntax — Markdown 基礎語法參考
- Python-Markdown: md_in_html Extension — Python-Markdown md_in_html 擴展文件
- GitHub Markup — GitHub 的 Markdown 渲染說明
- OWASP XSS Prevention Cheat Sheet — XSS 防護參考