💡 文章重點摘要:在前端面試與團隊 Code Review 中,最常出現的爭論莫過於:「一個 HTML 頁面裡到底能不能出現多個
<header>?」有人堅持全頁只能有一個頁首,也有人在每個卡片與章節都放<header>卻擔心會讓螢幕閱讀器抓狂。本文將依據 WHATWG HTML Living Standard 與 W3C HTML-AAM 1.0 官方規範,帶你徹底搞懂 多重 header 的上下文角色自動降級機制,並破除早已被廢除的「HTML5 Document Outline 大綱演算法」歷史迷思!
在上一篇《HTML5 header 內只能放標題嗎?剖析導覽列、搜尋框與巢狀結構的最佳實踐》中,我們拆解了單一 <header> 內部該如何擺放 Logo、<nav> 與 <search>。但當網頁規模擴大——同時包含「全站頂部導覽」、「主文章標頭」、「文章內的子章節導讀」以及「留言區每則讀者評論的標頭」時,我們就會面臨 多重 header 的架構設計問題。
究竟同一個頁面寫 4、5 個 <header> 合不合法?為什麼頂層 <header> 是全站地標,放進 <article> 裡就不是?各層 <header> 裡面的 <h1>、<h2>、<h3> 又該如何分配才不會搶走 SEO 權重?接下來我們直接從 30 秒即用範本與底層映射規則開始剖析!
⚡ 快速簡單使用(30 秒複製即用範本)
在同一份 HTML 文件中,你可以合法使用多個 <header>,只要確保**「全站頂層(<body> 直接子代)只有 1 個 <header>,其餘 <header> 皆包裹在 <article>、<section> 或 <aside> 等區段容器內」**。請直接複製以下標準四層架構範本:
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8">
<title>HTML5 多重 header 標準巢狀架構範本</title>
</head>
<body>
<!-- 1️⃣ 第 1 個 <header>(位於 <body> 頂層):W3C 自動映射為全站唯一 role="banner" 橫幅地標 -->
<header class="site-header">
<a href="/" class="brand-logo">Sean 的技術筆記</a>
<nav aria-label="主導覽選單">
<ul>
<li><a href="/html" aria-current="page">HTML 專欄</a></li>
<li><a href="/seo">SEO 指南</a></li>
</ul>
</nav>
</header>
<main>
<article class="post-article">
<!-- 2️⃣ 第 2 個 <header>(位於 <article> 內):自動降級為 role="generic",放全頁唯一 <h1> -->
<header class="article-header">
<h1>多重 header 怎麼用?HTML5 區段內容與頁首標籤的巢狀階層拆解</h1>
<p>作者:Sean · 發布於 <time datetime="2026-10-24">2026-10-24</time></p>
</header>
<!-- 3️⃣ 第 3 個 <header>(位於 <section> 內):自動降級為 role="generic",放章節 <h2> 與導讀 -->
<section class="chapter-section" aria-labelledby="ch1-title">
<header class="section-header">
<h2 id="ch1-title">一、 區段內容與多重頁首的底層映射關係</h2>
<p class="chapter-lead">本節將解析 W3C 無障礙樹如何根據父容器動態切換 header 的角色。</p>
</header>
<p>這裡是第一章節的正文段落...</p>
</section>
</article>
</main>
<!-- 4️⃣ 第 4 個 <header>(位於 <aside> 內):自動降級為 role="generic",放側欄區塊 <h2> -->
<aside class="sidebar" aria-labelledby="hot-posts-title">
<header class="widget-header">
<h2 id="hot-posts-title">本週熱門技術文章</h2>
</header>
<ul>
<li><a href="/html/html-header-vs-head-semantic-pitfalls/">head 與 header 的致命混淆</a></li>
</ul>
</aside>
</body>
</html>
一、 5 秒快速索引:多重 header 在不同父容器下的語意與角色速查表
許多工程師擔心:「如果一個頁面寫了 5 個 <header>,視障朋友的螢幕閱讀器會不會播報 5 個全站橫幅(Banner Landmark),害他們迷路?」
答案是:只要放對父容器,完全不會! 根據 W3C HTML Accessibility API Mappings 1.0 (HTML-AAM) 規範,瀏覽器會根據 <header> 的祖先元素自動切換其無障礙角色:
<header> 的所在位置(DOM 階層) | 所屬語意定位 | W3C 無障礙樹角色 (ARIA Role) | 內部推薦標題層級(單篇內頁) | 是否允許巢狀? |
|---|---|---|---|---|
<body> > <header>(無區段內容與 <main> 祖先) | 全站頂層頁首 (Global Site Header) | 🟢 role="banner"(全頁唯一橫幅地標) | 不放 <h1>(Logo 用 <a> 包裹,把 <h1> 留給文章) | ✅ 合法(全頁限 1 個頂層 banner) |
<article> > <header> | 獨立文章標頭 (Article Header) | 🔵 role="generic"(一般群組,非地標) | 全頁唯一 <h1>(單篇內頁)或 <h2>(列表卡片頁) | ✅ 合法(隨 <article> 數量配置) |
<section> > <header> | 主題章節標頭 (Section Header) | 🔵 role="generic"(一般群組,非地標) | <h2> 或 <h3>(搭配章節前言或統計摘要) | ✅ 合法(當章節除了標題還有導讀時使用) |
<aside> > <header> | 側欄模組標頭 (Sidebar Widget Header) | 🔵 role="generic"(一般群組,非地標) | <h2> 或 <h3>(側邊欄小工具標題) | ✅ 合法 |
<footer> > <header> 或 <header> > <header> | 非法結構 (Syntax Error) | 🔴 W3C 驗證器直接報錯 | 禁用 | ❌ 嚴格禁止(違反 WHATWG 內容模型) |
二、 深入底層:為什麼同一個頁面可以有多個 header 卻不會地標氾濫?
在 HTML4 時代,開發者只能用 <div id="header"> 建立全站唯一的頂部區塊。進入 HTML5 後,規範引入了 Sectioning Content(區段內容:<article>、<section>、<aside>、<nav>) 的概念(詳見《HTML 語意化標籤的邊界:談 section、article 與 aside 的巢狀邏輯陷阱》)。
請透過下圖觀察瀏覽器引擎在建構無障礙樹(Accessibility Tree)時,是如何聰明地為 多重 header 執行「上下文自動降級(Contextual Role Demotion)」:

1. W3C HTML-AAM 的「祖先攔截規則」
根據 W3C HTML-AAM 1.0 §3.4 (header element) 官方定義:
- 唯有當
<header>不是<article>、<aside>、<main>、<nav>或<section>的後代時,瀏覽器才會將它映射為role="banner"地標。 - 一旦
<header>被包裹在上述任何一個區段元素或<main>裡面,瀏覽器就會自動解除它的地標身分,改映射為role="generic"!
這項精妙的設計,確保了螢幕閱讀器使用者按下地標快捷鍵時,只會精準跳到全站最上方的唯一頂層<header>,而不會被文章內部或章節內部的局部<header>干擾。
2. ⚠️ 破除歷史迷思:別再相信早已被廢除的「HTML5 Document Outline 大綱演算法」!
許多舊教材或老文章在解釋 多重 header 時,會宣稱:「因為 <article> 與 <section> 會建立獨立的 Document Outline(文件大綱作用域),所以裡面的每個 <header> 都可以各自寫一個 <h1>!」
請立刻把這個過時觀念從腦中刪除!
事實上,當年 W3C / WHATWG 雖然曾提出過 Document Outline 演算法草案,但全球沒有任何一款主流瀏覽器(Chrome、Safari、Firefox)或螢幕閱讀器(NVDA、JAWS、VoiceOver)真正實作過這套演算法。因此,WHATWG 已於 2022 年正式從 HTML 標準規格書中徹底移除 Document Outline 演算法!
在 2026 年的現代網頁開發中,無論你的 <header> 包在幾層 <article> 或 <section> 裡面,整張網頁的標題階層永遠是全域計算的(全頁依然只應有 1 個主 <h1>,接著依序使用 <h2> ➔ <h3>)!
三、 標題層級(h1 / h2 / h3)在多重 header 中的黃金分配法則
既然不能在每個 <header> 都亂塞 <h1>,那麼當頁面同時存在多個 <header> 時,裡面的標題標籤該怎麼配?這取決於你的頁面屬於「單篇文章內頁」還是「文章列表/分類頁」:

情境 A:單篇文章內頁(Single Post Detail Page)
許多舊版部落格最大的 SEO 敗筆,就是在頂層 <header class="site-header"> 把網站名稱寫成 <h1>Sean 的技術筆記</h1>,然後把真正重要的文章標題 <article><header><h2>...</h2></header> 降級成 <h2>!這會導致全站幾百篇文章的 <h1> 通通長一樣,嚴重稀釋單篇文章的關鍵字權重。
- 正確分配:
<body> > <header class="site-header">:網站名稱與 Logo 使用<a href="/">(不包<h1>)。<main> > <article> > <header class="post-header">:放置**全頁唯一的<h1>(文章主標題)**與發布時間<time>。<article> > <section> > <header class="section-header">:放置章節標題<h2>與章節導言。- 留言區
<section> > <article class="comment"> > <header>:放置單則留言標題或留言者名稱<h3>。
情境 B:分類歸檔/文章卡片列表頁(Category / Archive Feed Page)
當頁面是顯示 10 篇文章預覽卡片的「HTML5 專欄列表頁」時,頁面有 10 個 <article class="post-card">,每個卡片都有自己的 <header>:
- 正確分配:
<body> > <header class="site-header">:網站 Logo 使用<a href="/">。<main> > <header class="archive-header">:放置**全頁唯一的<h1>(例如:<h1>HTML5 語意化實戰專欄</h1>)**與專欄介紹。- 底下 10 張
<article class="post-card"> > <header>:每張卡片的文章標題統一使用<h2><a href="...">文章標題</a></h2>!
四、 生產級實戰對決:從「大綱破版反模式」重構為「滿分多重 header 架構」
接下來我們透過完整的可執行代碼,對比「把 <h1> 給網站 Logo 且濫用 <header>」的錯誤寫法,與符合 WHATWG / W3C HTML-AAM 標準的生產級多重 <header> 架構。
1. ❌ 常見翻車反模式(全站 Logo 搶走 h1 + 在 footer 內塞 header)
<body>
<!-- ❌ 陷阱 1:把全頁唯一 <h1> 給了全站共用的網站名稱,害文章主標題被迫降為 <h2>! -->
<header class="site-header">
<h1>Sean 的技術筆記</h1>
</header>
<main>
<!-- ❌ 陷阱 2:直接在 <main> 底下寫第 2 個沒有被 <article>/<section> 包裹的裸露 <header>,易造成結構混淆 -->
<header class="announcement">全站系統維護公告</header>
<article>
<header>
<!-- ❌ 陷阱 3:真正的文章主標題卻被降級成 <h2>,傷害單文 SEO 主題權重 -->
<h2>多重 header 巢狀階層完整教學</h2>
</header>
<section>
<!-- ❌ 陷阱 4:如果章節只有單純一行 <h3> 標題、沒有任何副標或導言,多包一層 <header> 屬於多餘冗贅 -->
<header>
<h3>什麼時候需要章節 header?</h3>
</header>
<p>內文段落...</p>
</section>
</article>
</main>
<footer>
<!-- ❌ 陷阱 5:在 <footer> 裡面塞 <header>,直接違反 WHATWG 語法規範(HTML Validator 報錯)! -->
<header>
<h4>聯絡我們</h4>
</header>
<p>[email protected]</p>
</footer>
</body>
2. 🟢 生產級標準重構範例(含四層多重 header 與無障礙角色自動化驗證腳本)
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多重 header 怎麼用?HTML5 巢狀階層標準範例</title>
</head>
<body>
<!-- ✅ 第 1 層:全站頂層 <header> (唯一 role="banner" 地標) -->
<header class="site-header">
<a href="/" class="site-brand">Sean 的技術筆記</a>
<nav aria-label="主要選單">
<ul>
<li><a href="/html" aria-current="page">HTML 專欄</a></li>
<li><a href="/web-perf">效能調優</a></li>
</ul>
</nav>
</header>
<main>
<article class="main-article">
<!-- ✅ 第 2 層:主文章 <header> (位於 <article> 內 -> role="generic",擁有全頁唯一 <h1>) -->
<header class="article-header">
<hgroup>
<p class="category-badge">HTML5 架構實戰</p>
<h1>多重 header 怎麼用?HTML5 區段內容與頁首標籤的巢狀階層拆解</h1>
</hgroup>
<div class="post-meta">
<span>作者:Sean</span> ·
<time datetime="2026-10-24">2026 年 10 月 24 日</time> ·
<span>閱讀時間:6 分鐘</span>
</div>
</header>
<!-- ✅ 第 3 層:章節 <header> (當章節包含 <h2> + 導讀摘要/數據指標時,使用 <header> 群組化) -->
<section class="article-section" aria-labelledby="sec-architecture">
<header class="section-header">
<h2 id="sec-architecture">一、 企業級內容網站的多重標頭拓撲</h2>
<p class="section-summary">核心指標:全頁限 1 個頂層 banner 地標、1 個主標題 H1,其餘區段標頭自動降級為 generic。</p>
</header>
<p>當章節開頭除了標題之外,還附帶章節引言、最後更新時間或操作按鈕時,使用 <code><section> > <header></code> 就能將這組標頭資訊與下方正文段落清楚切分。</p>
</section>
<!-- ✅ 第 4 層:讀者留言區(巢狀 <article> 內的局部 <header>) -->
<section class="comments-section" aria-labelledby="sec-comments">
<h2 id="sec-comments">二、 讀者技術交流(共 1 則留言)</h2>
<article class="comment-item">
<header class="comment-header">
<h3>前端工程師 Leo</h3>
<p>留言於 <time datetime="2026-10-24T14:20:00+08:00">2026-10-24 14:20</time></p>
</header>
<p>原來以前學的 Document Outline 演算法已經在 2022 年被廢除了,把 H1 留給文章標題真的清楚多了!</p>
</article>
</section>
</article>
</main>
<footer class="site-footer">
<!-- ✅ 頁尾區塊直接使用標題或段落,絕不在 <footer> 內嵌套 <header> -->
<h2>關於本站</h2>
<p>© 2026 seanacnet.com All Rights Reserved.</p>
</footer>
<script>
// 🔍 生產環境自檢腳本:盤點全頁所有 <header> 的上下文角色與標題層級
function auditMultipleHeaders() {
const allHeaders = Array.from(document.querySelectorAll('header'));
const report = allHeaders.map((hdr, index) => {
const isScoped = hdr.closest('article, aside, main, nav, section') !== null;
const computedRole = isScoped ? 'generic (區段局部標頭)' : 'banner (全站頂層地標)';
const heading = hdr.querySelector('h1, h2, h3, h4, h5, h6');
return {
index: index + 1,
className: hdr.className,
w3cRole: computedRole,
headingTag: heading ? heading.tagName : '無 (Logo 導覽區)'
};
});
const bannerCount = report.filter(r => r.w3cRole.startsWith('banner')).length;
const h1Count = document.querySelectorAll('h1').length;
console.log('=== [多重 Header 階層與無障礙角色檢驗報告] ===');
console.log('全頁 <header> 總數:', allHeaders.length, '| 頂層 banner 地標數:', bannerCount, '| 全頁 <h1> 總數:', h1Count);
report.forEach(r => {
console.log(`#${r.index} .${r.className} ➔ W3C 角色: ${r.w3cRole} | 內部標題: ${r.headingTag}`);
});
}
auditMultipleHeaders();
</script>
</body>
</html>
Expected Output (預期 Console 輸出結果)
=== [多重 Header 階層與無障礙角色檢驗報告] ===
全頁 <header> 總數: 4 | 頂層 banner 地標數: 1 | 全頁 <h1> 總數: 1
#1 .site-header ➔ W3C 角色: banner (全站頂層地標) | 內部標題: 無 (Logo 導覽區)
#2 .article-header ➔ W3C 角色: generic (區段局部標頭) | 內部標題: H1
#3 .section-header ➔ W3C 角色: generic (區段局部標頭) | 內部標題: H2
#4 .comment-header ➔ W3C 角色: generic (區段局部標頭) | 內部標題: H3
五、 實務開發 4 大高頻踩坑雷區
在規劃複雜頁面的 多重 header 時,請特別留意以下 4 個實戰陷阱:
- 只有單獨一行
<h2>或<h3>時,過度包裝多餘的<header>(Header Wrapper Bloat):
如果某個<section>開頭只有孤零零的一行<h2>二、 系統需求</h2>,底下沒有任何副標題、沒有發布日期、也沒有操作按鈕,這時直接寫<h2>即可,不需要硬包一層<header><h2>...</h2></header>!<header>的價值在於「將標題與周圍的輔助介紹資訊(如<hgroup>、<time>、作者、篩選按鈕)打包成一個語意群組」,單一元素多包一層只會增加無意義的 DOM 深度。 - 在
<footer>裡面寫<header>(語法驗證直接失敗):
有些工程師在刻大型頁尾(Mega Footer)時,習慣在<footer>裡面的訂閱電子報區塊寫<header><h3>訂閱技術週報</h3></header>。請注意:WHATWG<footer>規範 (§4.3.8) 明文規定<footer>的後代元素中絕對禁止出現<header>或<footer>!這不是風格問題,而是 W3C Nu Html Checker 會直接報紅字的語法錯誤。 - 把文章內文的第一段
<p>誤包進<article>的<header>裡:<header>僅限容納「介紹性導言(Lead / Deck)、副標題與中繼資料(作者、日期、目錄)」。文章真正的正文段落必須放在<header>結束標籤</header>之後,否則螢幕閱讀器與閱讀模式(Reader Mode,如 Safari 閱讀器或 Pocket)在擷取文章正文時,可能會把包在<header>裡的段落略過! - 在
<body>頂層放了兩個未被區段包裹的<header>,導致雙重banner地標衝突:
如前文所述,任何沒被<article>、<section>、<aside>、<nav>或<main>包住的<header>,都會變成role="banner"頂層地標。根據 W3C 規範,一份文件最多只能有 1 個頂層banner地標;其餘局部<header>務必確認位於對應的區段容器內部。
六、 上線前 5 點自我檢驗清單 (Checklist)
在完成包含多重頁首的頁面切版後,請花 30 秒執行以下 5 點檢驗:
- ☐ 1. 頂層
banner地標唯一性檢查:確認整張網頁直接位於<body>底下的<header>只有 1 個,其餘<header>皆位於<article>、<section>、<aside>、<nav>或<main>內部。 - ☐ 2. 全頁
<h1>唯一性與標題遞進檢查:確認沒有誤信已廢除的 Document Outline 演算法而在多個<header>裡重複寫<h1>;單篇內頁的唯一<h1>位於主文章<article> > <header>內,子章節依序使用<h2>➔<h3>。 - ☐ 3. 零
footer > header或header > header非法嵌套:在 DevTools Console 執行document.querySelectorAll('footer header, header header, address header').length === 0確保回傳true。 - ☐ 4. 剔除單一標題的冗餘
<header>外殼:檢查各<section>內的<header>,若內部僅有單一<h2>而無任何副標題、導言或操作元件,已簡化為直接放置<h2>。 - ☐ 5. 瀏覽器閱讀模式(Reader Mode)實測:開啟 Safari 或 Firefox 的「閱讀模式」,確認文章主標題、作者日期與正文第一段皆能完整被擷取顯示,沒有因誤包進
<header>而遺失正文。
參考資料與延伸閱讀
- WHATWG HTML Living Standard: The
headerelement (§4.3.7) — 官方規範<header>可用於多個區段開頭,並提供同頁包含全站頁首與文章頁首之官方標準範例。 - WHATWG HTML Living Standard: Headings and outlines (§4.3.10) — 官方說明現代 HTML 標題層級(
<h1>~<h6>)的全域排名規則(已正式移除舊版 Document Outline 演算法)。 - WHATWG HTML Living Standard: The
footerelement (§4.3.8) — 官方明定<footer>的內容模型禁止包含<header>或<footer>後代元素。 - W3C HTML Accessibility API Mappings (HTML-AAM 1.0):
headercontextual role mapping — W3C 官方定義<header>在頂層映射為role="banner"與在區段內容內降級為role="generic"的無障礙標準。 - MDN Web Docs:
<header>: Usage notes & Multiple headers — Mozilla 開發者社群針對同頁使用多個<header>標籤的語意邊界與無障礙注意事項說明。
發表迴響