💡 文章重點摘要:當前端團隊跨越了「全頁
<div>」的初階階段後,在使用 HTML 語意化標籤時往往會掉入更隱蔽的「巢狀邏輯陷阱」——例如把全站廣告<aside>塞進<article>正文裡,讓廣告在語意上變成文章的一部分、為頁面上的十幾個<section>全部加上aria-label引發螢幕閱讀器「地標氾濫」,或是不知道<header>、<footer>與<aside>被包進區段容器後底層 ARIA 角色會發生劇變。本文將從 W3C HTML-AAM 上下文敏感語意(Context-Dependent Semantics)與 Accessible Name 計算規範切入,帶你徹底征服<section>、<article>與<aside>的進階巢狀邊界!
⚡ 快速簡單使用(30 秒複製即用範本)
如果你想立刻避開 <article>、<section> 與 <aside> 最容易踩中的巢狀語意汙染(全站側邊欄與文章附註分離、只為核心區段命名 aria-labelledby),可直接複製下方標準結構範本:
<div class="page-layout">
<main>
<article class="post-article">
<header>
<h1>文章主標題</h1>
</header>
<!-- 1. 一般章節 <section>:不加 aria-label,避免引發全頁 Region 地標氾濫 -->
<section>
<h2>第一章:核心架構</h2>
<p>正文內容...</p>
<!-- 2. 嵌套於 <article> 內的 <aside>:僅限放「與這篇文章直接相關」的名詞解釋或延伸閱讀 -->
<aside aria-label="名詞補充說明">
<p>小百科:HTML-AAM 是 W3C 定義標籤如何映射至無障礙樹的規範。</p>
</aside>
</section>
</article>
</main>
<!-- 3. 位於 <article> 外部的頂層 <aside>:放置全站熱門排行、站內廣告等全站級補充資訊 -->
<aside aria-label="全站熱門文章與推薦">
<h2>熱門排行</h2>
</aside>
</div>
💡 3 秒修改重點:
- 全站共用側邊欄/廣告
<aside>必須放在<article>外面:<article>代表可獨立分發的完整內容,放在裡面的廣告在語意上就成了文章的一部分;而且位於<article>內、沒有無障礙名稱的<aside>只會映射為generic,不是complementary地標。- 只有需要讓使用者用地標直接跳轉的核心
<section>才加aria-labelledby,一般章節請保持無命名狀態。
一、 為什麼標籤「放的位置不同」,底層語意就會變?上下文敏感語意揭秘
許多工程師以為一個 HTML 標籤的語意是固定不變的。然而根據 W3C HTML Accessibility API Mappings (HTML-AAM 1.0) 規範,HTML5 的區段與地標標籤具有強烈的「上下文敏感性(Context-Dependent Semantics)」——同一個標籤放在 <body> 頂層,與被嵌套進 <article>、<section>、<nav>、<aside> 等區段內容(Sectioning Content)內部時,瀏覽器賦予它的無障礙樹角色(ARIA Role)會截然不同!(<header>/<footer> 放進 <main> 內也會改變角色;<aside> 放在 <main> 內則仍是 complementary。)

<header>/<footer> 位於 <article>/<section>/<main> 內映射為 generic,為 2026-02-25 以前 HTML-AAM 的舊版映射,現行映射見下方「規範新舊差異」)規範新舊差異:區段內 header/footer 與 aside 的現行映射
依現行 HTML-AAM 的元素映射表,上下文對角色的影響如下:
| 元素與位置 | 現行映射 | 舊版映射與變更出處 |
|---|---|---|
<header> 位於 <body> 頂層 | banner 地標 | 未變更 |
<header> 位於 <main> 或區段內容內 | sectionheader | 舊版為 generic(HTML-AAM 2022-03-06 變更紀錄,GitHub PR #364);2026-02-25 w3c/aria PR #2543 合併後改為 sectionheader |
<footer> 位於 <body> 頂層 | contentinfo 地標 | 未變更 |
<footer> 位於 <main> 或區段內容內 | sectionfooter | 同上,舊版為 generic,2026-02-25 起改為 sectionfooter |
<aside> 位於 <body> 或 <main> 內 | complementary 地標 | 未變更 |
<aside> 位於區段內容內 | 有無障礙名稱時為 complementary,否則為 generic | 2022-04-03 起依巢狀位置區分(HTML-AAM 變更紀錄,GitHub PR #350) |
sectionheader/sectionfooter 不是地標,HTML-AAM 也註明瀏覽器與輔助科技在元素沒有無障礙名稱、不可聚焦且沒有其他可公開資訊時,可以不公開這兩個角色。重點不變:區段內的 <header>/<footer> 不會成為 banner/contentinfo 全站地標。以 Chrome 156 載入本文範例時,<article> 內的 <header> 在無障礙樹中顯示為 sectionheader。
二、 5 秒快速索引:section、article、aside 進階巢狀合法性速查表
在設計複雜版面的 DOM 結構時,請先查閱這張巢狀組合(Nesting Combinations)語意合法性與底層行為矩陣:
| 外層父容器 ➔ 內層子元素 | 語法與語意合法性 | 底層結構意義與瀏覽器解析行為 | 真實生產環境應用場景 |
|---|---|---|---|
<article> ➔ <section> | 🟢 標準推薦 | 將一篇獨立完整的文章,依主題拆分為多個有標題(<h2>~<h3>)的章節。 | 長篇技術教學文內部的「環境建置」、「核心語法」、「踩坑要點」章節。 |
<section> ➔ <article> | 🟢 標準推薦 | 在一個主題分組區域內,陳列多個可獨立分發(Syndicatable)的自包含內容單元。 | 首頁「最新消息區 <section>」內含 6 張獨立新聞卡片 <article>。 |
<article> ➔ <article> | 🟡 有條件合法 | 內層 <article> 代表與外層 <article> 內容相關的文章(附屬於主文的獨立單元)。 | 部落格主文章 <article> 底部的單則讀者留言 <article>(嚴禁放無關的外部商品卡)。 |
<article> ➔ <aside> | 🟢 標準推薦 | 代表與該篇 <article> 內容間接相關的補充說明(屬於文章的一部分;沒有無障礙名稱時映射為 generic,有名稱才是 complementary)。 | 文章段落旁的「名詞解釋小辭典」、「作者引言框(Pull Quote)」、「背景數據補充」。 |
<body> ➔ <aside> | 🟢 標準推薦 | 代表與整個網站/頁面間接相關的全站級側邊欄(role="complementary" 地標)。 | 全站熱門文章排行榜、全站分類目錄、站內外廣告版位(不屬於單篇文章正文)。 |
<section> ➔ <section> | 🟢 合法(巢狀過深需檢討) | 代表大章節下的子章節(例如 <h2> 區塊內包 <h3> 子區塊)。 | 僅限大型規格書或長文;若巢狀超過 3 層且無對應標題,通常屬於過度包裝(Over-nesting)。 |
三、 陷阱一:aside 放 article 裡還是放外面?失之毫釐、差之千里!
在已經熟悉 HTML5 語意化標籤基礎分界之後,工程師最常搞砸的就是 <aside> 的擺放層級。
根據 WHATWG <aside> 官方規範,<aside> 代表與「它周圍內容」間接相關的內容,所以它放在哪一層,就決定了它「依附於誰」:
- 當
<aside>放在<article>內部時:它代表這篇文章本身的附註(例如針對文中某個專有名詞的側欄補充、勘誤表或參考文獻框),跟著文章一起被分發或重用也合理。依 HTML-AAM,這種<aside>有無障礙名稱時才是complementary地標,沒有名稱則映射為generic。 - 當
<aside>放在<article>外部(與<main>並列)時:它代表整個網頁的附屬側邊欄(例如全站導覽連結、站長簡介、Google AdSense 廣告或熱門文章推薦)。
實作程式碼對比:文章內附註 aside vs 全站側邊欄 aside
<!-- 🟢 正確示範:精準區分「文章級附註 aside」與「全站級側邊欄 aside」 -->
<div class="page-layout">
<main class="main-column">
<article class="tech-article">
<h1>深入理解 V8 引擎垃圾回收機制</h1>
<p>在 JavaScript 中,多數物件都被分配在 Heap(堆積)記憶體中...</p>
<!-- ✅ 情境 A:位於 <article> 內部的 <aside> -->
<!-- 語意:與本篇文章直接相關的名詞小百科,隨文章一起分發依然合理 -->
<aside class="article-glossary-box" aria-label="專有名詞小百科">
<h2>💡 什麼是 Stop-The-World (全停頓)?</h2>
<p>指垃圾回收器執行標記與清理時,暫停主執行緒 JavaScript 程式碼執行的現象。</p>
</aside>
<section aria-labelledby="gen-gc">
<h2 id="gen-gc">一、 分代回收假設 (Generational Hypothesis)</h2>
<p>V8 將記憶體分為新生代(New Space)與老生代(Old Space)...</p>
</section>
</article>
</main>
<!-- ✅ 情境 B:位於 <main> 與 <article> 外部的頂層 <aside> -->
<!-- 語意:全站共用的側邊資訊欄,與單篇文章正文無關,避免汙染文章主體與閱讀模式 -->
<aside class="global-sidebar" aria-label="全站熱門與贊助資訊">
<section class="widget">
<h2>全站熱門文章排行</h2>
<ul>
<li><a href="/html/what-is-dom-tree-reflow-repaint-guide/">DOM 樹與渲染引擎揭秘</a></li>
</ul>
</section>
</aside>
</div>
Expected Output (預期解析行為)
以 Chrome 156 載入上方範例,無障礙樹中的地標與區段節點如下:
mainarticle內的complementary "專有名詞小百科"(位於<article>內,因為有aria-label才成為complementary;拿掉aria-label會變成generic)article內的region "一、 分代回收假設 (Generational Hypothesis)"(aria-labelledby指向<h2>)- 頁面外層的
complementary "全站熱門與贊助資訊" - 螢幕閱讀器地標導航:使用者可清楚區分位於文章內的「專有名詞小百科」與位於頁面外層的「全站熱門與贊助資訊」兩個補充內容地標。
四、 陷阱二:section 的「地標氾濫災難」與 Accessible Name 計算規則
這是許多中階工程師最容易誤解的規範細節。坊間常有錯誤教學宣稱:「只要寫了 <section>,螢幕閱讀器就會把它當成地標(Landmark),所以要幫每個 <section> 都加上 aria-label!」
讓我們嚴格對照 W3C 官方規範執行「去偽留真」糾正:
- 無名
<section>根本不是地標!
根據 W3C HTML-AAM 規範(section有無障礙名稱時為region,否則為generic),一個沒有掛載aria-labelledby、aria-label或title的<section>,在無障礙樹中的角色是role="generic"(跟<div>一模一樣),螢幕閱讀器按地標快捷鍵時完全不會停在它上面! - 幫所有
<section>加上aria-label才會引發真正的災難!
一旦你為<section>加上了無障礙名稱(Accessible Name),它就會瞬間升格為role="region"地標。如果一篇文章有 12 個小節,你把 12 個<section>全部綁上aria-labelledby,視障使用者的地標選單就會被 12 個 Region 塞爆,形成地標氾濫,反而讓地標快速跳轉失去意義!W3C APG 的 Landmark Regions 對region的定義是「內容重要到使用者需要能直接跳轉過去的區段」,並要求頁面上有多個region時各自使用不同的名稱。
W3C 無障礙名稱計算(Accessible Name Computation)與地標升格決策圖

💡 W3C Accessible Name 優先級鐵律:
依 Accessible Name and Description Computation 1.2,當一個元素同時存在多種命名來源時,瀏覽器計算無障礙名稱的優先順序為:aria-labelledby(最高優先,甚至會覆蓋aria-label!) ➔aria-label➔ 宿主語言的原生標示(如<label>、alt) ➔title屬性(最後備援)。region角色不從內部文字取名,所以<section>裡的<h2>不會自動變成它的名稱。因此,只要畫面上已經有<h2>標題,請永遠優先使用aria-labelledby參照該標題的id,絕對不要重複手寫一份aria-label(避免日後改了<h2>文字卻忘記改aria-label造成語音與畫面不一致)。
五、 陷阱三:article 嵌套 article 的嚴格語意契約
在 WHATWG 規範中,<article> 是允許嵌套 <article> 的,但規範寫明:巢狀時,內層的 <article> 代表「原則上與外層文章內容相關」的文章,並以部落格文章底下的讀者留言作為例子。換句話說,內層的 <article> 必須在語意上與外層的 <article> 相關!
❌ 錯誤示範:把「全站推薦商品卡片」塞進技術文章 article 內部
<!-- ❌ 嚴重語意汙染:把與本文無關的電商促銷卡片塞在主文章 <article> 裡面 -->
<article class="blog-post">
<h1>CSS Grid 網格佈局完整解析</h1>
<p>Grid 是二維排版系統...</p>
<!-- 💥 錯誤!這張機械鍵盤促銷卡與 CSS Grid 文章本身毫無附屬關係 -->
<article class="promo-product-card">
<h2>限時特價:RGB 機械式鍵盤</h2>
<p>只要 NT$ 1,990,立即搶購!</p>
</article>
</article>
🟢 正確示範:僅將「隸屬於該文章的讀者留言」嵌套於主 article(或抽離至平行 section)
<!-- 🟢 正確結構:內層 <article> 為針對本篇主文章的讀者回應,符合附屬關聯規範 -->
<article class="blog-post">
<header>
<h1>CSS Grid 網格佈局完整解析</h1>
</header>
<p>Grid 是二維排版系統,能同時處理欄與列...</p>
<section class="comments-area" aria-labelledby="comments-heading">
<h2 id="comments-heading">讀者留言討論 (2)</h2>
<!-- 內層 article:單則讀者評論,隸屬於外層文章且具備獨立作者與時間 -->
<article class="comment-card" id="comment-101">
<header>
<h3>前端小新 <span class="badge">作者認證</span></h3>
<time datetime="2026-10-22T14:20:00">2026-10-22 14:20</time>
</header>
<p>感謝分享!終於搞懂 Grid 跟 Flexbox 的搭配時機了。</p>
</article>
</section>
</article>
六、 如何用現代 Chrome DevTools 驗證語意樹與巢狀結構?
寫完 HTML 後,請切勿使用早已過時且依據廢除演算法設計的舊式「HTML5 Outliner」擴充套件!請直接使用 Chrome 內建的 Accessibility Tree(無障礙樹檢視器)進行權威驗證:
- 開啟 Chrome DevTools (
F12) 並切換至 Elements 面板,在 DOM 樹中選取要檢查的元素。 - 點擊 Accessibility 分頁(面板較窄時可能收在「更多分頁」按鈕裡)。
- 開啟 Show accessibility tree 開關,Elements 面板的 DOM 樹會換成整頁無障礙樹;再關掉開關即可切回 DOM 樹,原本選取的節點會保持選取。
- 3 秒檢查重點:
- 觀察整頁的地標節點(
banner、navigation、main、region、complementary、contentinfo)是否只出現在真正需要跳轉的區塊(避免地標氾濫)。 - 點開每個
region與navigation,確認是否都有清楚的無障礙名稱(例如region "讀者留言討論 (2)");同類型地標有多個時,名稱不要重複。
- 觀察整頁的地標節點(
七、 工程師上線前必備:語意標籤巢狀邏輯檢驗清單 (Checklist)
- ☐
<aside>層級檢核:文章內部的名詞補充框放在<article>內;全站共用的熱門排行、分類與廣告欄<aside>則放在<article>與<main>外部。 - ☐ 拒絕 Region 地標氾濫:全頁僅針對「大型核心功能區(如搜尋篩選、留言區、FAQ)」的
<section>綁定aria-labelledby;一般文章內文小節<section>僅放<h2>/<h3>,不濫加aria-label。 - ☐ 優先使用
aria-labelledby:凡區塊內已有可見標題者,一律使用aria-labelledby="標題ID"綁定名稱,不重複手寫aria-label字串。 - ☐
<article>巢狀純淨度:主<article>內部絕無混入與該文章無關的外部廣告或全站推薦卡片。 - ☐ 區段內
<header>/<footer>不誤用:確認<article>或<section>內部的<header>與<footer>內沒有再嵌套另一個<header>或<footer>(WHATWG 語法嚴格禁止<header>包<header>)。
八、 參考資料與延伸閱讀
- W3C HTML Accessibility API Mappings (HTML-AAM 1.0) – W3C 官方規範:詳列
<section>、<aside>、<header>、<footer>在不同父容器上下文中的 ARIA Role 映射規則。 - w3c/aria PR #2543:Add header (sectionheader) and footer (sectionfooter) html-aam mappings – 2026-02-25 合併,區段內
<header>/<footer>由generic改為sectionheader/sectionfooter的變更出處。 - W3C Accessible Name and Description Computation 1.2 – 無障礙名稱計算步驟與各命名來源的優先順序。
- W3C WAI-ARIA Authoring Practices Guide (APG): Landmark Regions – W3C 無障礙地標設計要點,說明
region地標的使用時機與命名規則。 - Chrome DevTools: Accessibility features reference – Chrome 官方文件:Accessibility 分頁與 Show accessibility tree 開關。
- WHATWG HTML Living Standard: The aside element – HTML 官方規格書對
<aside>在文章內部與文章外部兩種語意情境的標準定義。 - MDN Web Docs: Document and website structure – Mozilla 官方教學:如何規劃語意化文件結構與無障礙大綱。
發佈留言