紀錄工作經驗、相關知識,解決技術相關問題。

HTML, 新手 Jamp Holes

HTML5 語意化標籤(Semantic Tags)徹底解析:為什麼你的 section 和 article 總是用錯?

HTML5 語意化標籤(Semantic Tags)徹底解析:為什麼你的 和 總是用錯? 特色圖片

💡 文章重點摘要:在日常專案開發與 Code Review 中,前端工程師使用 HTML5 語意化標籤時常陷入兩個極端:要嘛整頁從頭到尾用 <div class="section"> 煮出一鍋「Div 濃湯(Div Soup)」;要嘛患上「語意化強迫症」,把所有用來排版 Flexbox 的 <div> 全數無腦替換成 <section>,甚至在每個 <section> 裡都塞一個 <h1>!本文將從 WHATWG 官方標準與 W3C HTML-AAM 無障礙映射規範切入,帶你透過 3 秒黃金選型決策樹徹底搞懂 <article>、<section> 與 <div> 的分界線,並拆解雙向巢狀架構與 4 大生產環境語意化地雷!


⚡ 快速簡單使用(30 秒複製即用範本)

如果你想立刻搞清楚何時該用 <article>、<section> 與 <div> 這三大 HTML5 語意化標籤,直接複製下方標準頁面骨架修改即可:

<main>
  <!-- 1. <article>:抽離到 RSS 或外部網站依然「完整獨立」的內容(如單篇文章、商品卡、評論) -->
  <article class="blog-post">
    <h1>HTML5 語意化標籤實戰指南</h1>

    <!-- 2. <section>:具有明確標題 (h2~h6) 的「主題章節」,搭配 aria-labelledby 升格為無障礙地標 -->
    <section aria-labelledby="sec-intro">
      <h2 id="sec-intro">一、核心概念介紹</h2>
      <p>章節內文...</p>
    </section>

    <!-- 3. <div>:沒有獨立語意、純粹為了 Flexbox / Grid 視覺排版或背景樣式而生的容器 -->
    <div class="d-flex gap-3">
      <button type="button">分享文章</button>
      <button type="button">加入收藏</button>
    </div>
  </article>
</main>

💡 3 秒修改重點:

  1. 能獨立分發(如卡片、文章、留言) ➔ 用 <article>。
  2. 有明確小標題的主題章節 ➔ 用 <section>;純 CSS 排版外框 ➔ 用 <div>!

一、 為什麼你的 section 和 article 總是用錯?3 秒黃金選型決策樹

許多工程師分不清 <article>、<section> 與 <div>,是因為誤用「區塊面積大小」來決定標籤(例如以為大區塊用 <section>、小區塊用 <article> 或 <div>)。

事實上,在 WHATWG HTML Living Standard 規範中,這三者的唯一分界標準是「內容的獨立分發性(Syndicatable)」與「主題完整性(Thematic Grouping)」。在切版敲下鍵盤前,請直接照著這棵 3 秒黃金選型決策樹走一遍:

為什麼你的  和  總是用錯?3 秒黃金選型決策樹 視覺化架構流程圖
圖:為什麼你的 和 總是用錯?3 秒黃金選型決策樹 視覺化架構流程圖

二、 5 秒快速索引:HTML5 核心結構標籤與 W3C 無障礙映射速查表

在開發與審查程式碼時,除了理解語意,更要清楚瀏覽器底層是如何根據 W3C HTML-AAM(HTML Accessibility API Mappings)將這些標籤映射到無障礙樹(Accessibility Tree)中:

標籤名稱WHATWG 核心語意定義W3C 無障礙樹隱含角色 (Implicit ARIA Role)可否獨立分發典型實戰場景與生產環境鐵律
<article>獨立、自包含(Self-contained)之完整內容單元role="article"✅ 可以部落格正文、新聞卡片、商品卡、單則留言。內部應包含自己的標題(如 <h1> 或 <h2>/<h3>)。
<section>文件或應用中的主題式內容群組(Thematic Grouping)⚠️ 預設為 role="generic"
(唯有設定 aria-labelledby 或 aria-label 時才升格為 role="region" 地標!)
❌ 否頁面的功能章節(如「關於我們」、「常見問題」)。鐵律:沒有標題的區塊請勿用 <section>。
<div>零語意(Generic)的通用流式容器role="generic"❌ 否純 CSS 排版(.container、.grid-row、.card-body)。不要因為用了 <div> 而感到罪惡!
<main>當前頁面獨一無二的核心主內容role="main" (地標)❌ 否包覆頁面核心內容;全頁僅限 1 個可見的 <main>,且不可包含跨頁重複的側邊欄或導覽列。
<aside>與主內容間接相關的附屬或補充資訊role="complementary" (地標)
(位於頂層或 <section> 外時)
❌ 否側邊熱門文章欄、作者簡介卡、目錄欄、廣告版位。應與 <main> 並列而非塞進正文段落中。
<header>頁面或區段的引導標頭區位於 <body> 頂層時為 role="banner";位於 <article> / <section> 內為 role="generic"❌ 否放置全站 Logo 與主選單 <nav>;或放在 <article> 開頭包覆文章標題、作者與發布時間 <time>。
<footer>頁面或區段的結尾資訊區位於 <body> 頂層時為 role="contentinfo";位於區段內為 role="generic"❌ 否全站頁尾版權與法規連結;或放在 <article> 底部包覆文章分類標籤與作者簽名。

三、 深度架構拆解:article 與 section 誰包誰?雙向巢狀拓撲揭秘

新手最常問的問題是:「到底是 <article> 裡面包 <section>,還是 <section> 裡面包 <article>?」

答案是:兩者完全合法,而且在同一個真實商業頁面中往往同時存在!

  1. <article> 包 <section>(一篇文章拆分為多個主題章節):當使用者閱讀一篇長篇技術文章(<article>)時,文章內部的「前言背景」、「核心架構」、「實戰程式碼」各自構成一個有標題的子主題,因此使用 <section> 包覆。
  2. <section> 包 <article>(一個主題區塊內含多個獨立可分發單元):在文章底部的「讀者留言討論區(<section>)」或「延伸閱讀推薦區(<section>)」中,每一則留言、每一張推薦文章卡片都是可以獨立抽離的完整內容單元,因此卡片本身使用 <article> 包覆!
深度架構拆解: 與  誰包誰?雙向巢狀拓撲揭秘 視覺化架構流程圖
圖:深度架構拆解: 與 誰包誰?雙向巢狀拓撲揭秘 視覺化架構流程圖

四、 生產級實戰:從「Div 濃湯」重構為滿分 HTML5 語意化雙欄架構

讓我們透過一個真實的技術部落格文章頁,對比充滿結構缺陷的「Div 濃湯」與符合 Google SEO、W3C HTML-AAM 及 WCAG 無障礙規範的生產級架構。

1. ❌ 舊版反模式:無限 div 堆疊(Div Soup)

<!-- ❌ 錯誤示範:爬蟲與螢幕閱讀器眼中只有一坨扁平無意義的方塊 -->
<div class="header">
  <div class="site-brand">Sean 的技術筆記</div>
  <div class="nav">
    <a href="/">首頁</a>
    <a href="/html">HTML 專欄</a>
  </div>
</div>

<div class="page-wrapper">
  <div class="main-column">
    <div class="post-title">HTML5 語意化標籤徹底解析</div>
    <div class="post-meta">發布於 2026-10-22</div>
    <div class="post-block">
      <div class="sub-title">一、為什麼需要語意化?</div>
      <div class="text">因為搜尋引擎與輔助科技需要理解結構...</div>
    </div>
  </div>
  <div class="sidebar-column">
    <div class="widget-title">熱門排行</div>
    <div class="widget-list">...</div>
  </div>
</div>

<div class="footer">© 2026 Sean AC Net.</div>

2. 🟢 現代生產環境標準:語意化標籤與純排版 div 的完美分工

請特別觀察以下程式碼中的 3 個關鍵工程細節:

  1. 全頁唯一 <h1> 留給文章主標題:頂部網站品牌名稱使用一般連結 <a class="brand-logo">,避免全站每篇文章的 <h1> 都變成網站名稱。
  2. 純雙欄 Grid 外框依然使用 <div class="layout-container">,且 <aside class="site-sidebar"> 與 <main> 保持平行兄弟關係(不把全站側邊欄塞進 <main> 內)。
  3. 關鍵主題區塊透過 aria-labelledby 綁定標題 ID,使其在無障礙樹中正式升格為具名的 role="region" 地標!
<!-- 🟢 最佳實踐:HTML5 語意化結構與 CSS Grid 容器各司其職 -->
<header class="site-header">
  <div class="header-inner">
    <a href="/" class="brand-logo">Sean 的技術筆記</a>
    <nav aria-label="全站主選單">
      <ul role="list">
        <li><a href="/">首頁</a></li>
        <li><a href="/html" aria-current="page">HTML 專欄</a></li>
      </ul>
    </nav>
  </div>
</header>

<!-- 純視覺雙欄 Grid 排版外框:毫無語意負擔地使用 div -->
<div class="layout-container">
  <!-- 頁面唯一核心主內容區 -->
  <main id="main-content" class="site-main">
    <!-- 可獨立分發的完整技術文章 -->
    <article class="blog-post">
      <header class="post-header">
        <!-- 全頁唯一的 h1 標題,精準鎖定本文 SEO 核心關鍵字 -->
        <h1>HTML5 語意化標籤(Semantic Tags)徹底解析</h1>
        <p class="post-meta">
          發布日期:<time datetime="2026-10-22">2026 年 10 月 22 日</time>
        </p>
      </header>

      <!-- 文章內部主題章節 1 -->
      <section class="post-section" aria-labelledby="sec-why">
        <h2 id="sec-why">一、 為什麼現代網頁需要語意化標籤?</h2>
        <p>搜尋引擎爬蟲與螢幕閱讀器皆依賴語意標籤建立頁面結構索引...</p>
      </section>

      <!-- 文章內部主題章節 2 -->
      <section class="post-section" aria-labelledby="sec-boundary">
        <h2 id="sec-boundary">二、 section、article 與 div 的分界點</h2>
        <p>判斷核心在於是否具備獨立分發性與主題標題...</p>
      </section>

      <footer class="post-footer">
        <p>文章分類:<a href="/category/html" rel="tag">HTML</a></p>
      </footer>
    </article>

    <!-- 延伸閱讀主題區塊(section 內部包覆多個獨立的推薦卡片 article) -->
    <section class="related-posts" aria-labelledby="related-heading">
      <h2 id="related-heading">延伸閱讀推薦</h2>
      <div class="card-grid">
        <article class="post-card">
          <h3><a href="/html/what-is-dom-tree-reflow-repaint-guide/">DOM 樹狀結構與渲染引擎揭秘</a></h3>
          <p>深入理解瀏覽器如何將 HTML 轉換為記憶體樹狀物件...</p>
        </article>
        <article class="post-card">
          <h3><a href="/website-optimization/wcag-accessibility-standards-overview/">WCAG 無障礙指南完全解析</a></h3>
          <p>掌握 POUR 四大原則與 AA 等級色彩對比度規範...</p>
        </article>
      </div>
    </section>
  </main>

  <!-- 與主內容間接相關的全站側邊欄:與 <main> 並列,預設具備 role="complementary" 地標 -->
  <aside class="site-sidebar" aria-label="側邊熱門資訊欄">
    <section class="sidebar-widget" aria-labelledby="hot-posts-title">
      <h2 id="hot-posts-title" class="widget-heading">本週熱門文章</h2>
      <ul>
        <li><a href="/html/html-global-attributes-guide-data-aria/">HTML 全域屬性 data-* 與 aria-* 完全指南</a></li>
      </ul>
    </section>
  </aside>
</div>

<footer class="site-footer">
  <p>© 2026 Sean AC Net. All rights reserved.</p>
</footer>

Expected Output (預期解析與渲染結果)

當瀏覽器載入上述結構並打開 Chrome DevTools Accessibility Tree(無障礙樹)與 SEO 檢測工具時,會產出極度清晰的階層結構:

  1. 地標清單(Landmarks):
    • banner(頂部 <header>) ➔ 內含 navigation "全站主選單"(<nav>)
    • main(主內容區 <main>) ➔ 內含 article 與具名區段 region "延伸閱讀推薦"
    • complementary "側邊熱門資訊欄"(側邊欄 <aside>)
    • contentinfo(頁尾 <footer>)
  2. 標題大綱(Heading Hierarchy):
    • H1: HTML5 語意化標籤(Semantic Tags)徹底解析 (全頁唯一)
      • H2: 一、 為什麼現代網頁需要語意化標籤?
      • H2: 二、 section、article 與 div 的分界點
      • H2: 延伸閱讀推薦
        • H3: DOM 樹狀結構與渲染引擎揭秘
        • H3: WCAG 無障礙指南完全解析
      • H2: 本週熱門文章

五、 生產環境常見的 4 大語意化踩坑與歷史迷思 (Pitfalls & Troubleshooting)

地雷 1:誤信遠古「HTML5 Document Outline 演算法」,在每個 section 與 article 裡都寫 h1

  • ❌ 錯誤寫法:許多十年前的舊教學宣稱:「HTML5 的 <section> 和 <article> 會建立獨立的大綱作用域,所以裡面全部都可以從 <h1> 開始寫,瀏覽器會自動幫你降級成第二層、第三層標題!」
  • 💥 為什麼會壞(真相查核):全球沒有任何一款主流瀏覽器或螢幕閱讀器真正實作過 HTML5 Document Outline 演算法! 而且 WHATWG 官方已於 2022 年正式從 HTML 標準規格中徹底刪除了這套演算法。如果你在一個頁面的 5 個 <section> 裡寫了 5 個 <h1>,螢幕閱讀器與搜尋引擎看到的就是 5 個平起平坐的一級標題,整個文件層級徹底扁平化!
  • 解決思路:無論你的 <section> 或 <article> 嵌套有多深,全頁永遠嚴格遵守單一 <h1> ➔ <h2> ➔ <h3> 的真實數字遞進階層(若視覺字體大小不合預期,請透過 .h4、.h5 CSS class 控制外觀,絕不可跳階亂寫 HTML 標題標籤)。

地雷 2:患上「section 強迫症」,拿 section 當作 Flexbox / Grid 排版外框

  • ❌ 錯誤寫法:<section class="d-flex justify-content-between"><button>取消</button><button>確認</button></section>。
  • 💥 為什麼會壞:WHATWG 規格明確指出:「<section> 不是通用容器元素。當某個元素僅僅是為了提供樣式設定(Styling)或腳本操作(Scripting)的掛鉤時,鼓勵作者使用 <div>。」沒有主題與標題的 <section> 不僅違反規範,還會讓程式碼審查者誤以為漏寫了章節標題。
  • 解決思路:只要該容器內部沒有(也不適合有)<h2>~<h6> 主題標題,請一律使用 <div>。

地雷 3:以為寫了 section 螢幕閱讀器就能當成地標跳轉,卻沒綁定名稱

  • ❌ 踩坑現象:切版時把重要區塊都包了 <section>,但用螢幕閱讀器測試地標跳轉(按 D 鍵)時,卻完全跳不到這些 <section>!
  • 💥 為什麼會壞:根據 W3C HTML-AAM 1.0 官方規範,為了防止滿坑滿谷的無名 <section> 塞爆視障使用者的地標選單,瀏覽器規定:沒有無障礙名稱(Accessible Name)的 <section>,在無障礙樹中的角色僅為 role="generic"(與 <div> 完全相同)!
  • 解決思路:針對頁面中真正需要讓使用者快速跳轉的核心大區塊(如「產品規格區」、「常見問題區」、「延伸閱讀區」),在 <section> 加上 aria-labelledby="標題ID" 指向內部的 <h2>,它就會自動升格為具名的 role="region" 地標(注意:一般文章內文的小節無需每一個都升格為地標,避免地標過多造成干擾)。

地雷 4:把全站共用的側邊欄 aside 塞進 main 標籤裡面

  • ❌ 錯誤寫法:為了方便在 <main> 上直接下 display: grid; grid-template-columns: 3fr 1fr;,就把全站共用的熱門文章 <aside> 寫成 <main> 的子元素。
  • 💥 為什麼會壞:<main> 的定義是「排除全站跨頁重複區塊後的當前頁面專屬內容」。將全站側邊欄塞進 <main>,不僅削弱了搜尋引擎對正文核心區的純度判定,在部分舊版輔助工具中也會影響 <aside> 作為全站級 role="complementary" 地標的識別。
  • 解決思路:外層多包一個 <div class="layout-container"> 負責 CSS Grid 雙欄排版,讓 <main> 與 <aside> 在裡面平起平坐!

六、 工程師上線前必備:HTML5 語意化結構實務檢驗清單 (Checklist)

在提交 PR 或頁面上線前,請花 30 秒對照以下 5 點清單進行自我審查:

  • ☐ 唯一 <h1> 與無跳階標題:全頁僅有 1 個 <h1>(位於頁面核心主旨標題),且所有 <section> 與 <article> 內部的標題嚴格遵循 <h1> ➔ <h2> ➔ <h3> 順序,無跳階(如 h2 直接跳 h4)或多重 <h1>。
  • ☐ <article> 獨立分發檢核:所有使用 <article> 的區塊(主文章、推薦卡片、讀者留言),抽離當前頁面後皆具備獨立完整的上下文意義。
  • ☐ <section> 必備標題檢核:頁面中每一個 <section> 內部皆包含對應的主題標題(<h2>~<h6>);凡無標題的純排版容器已全數改回 <div>。
  • ☐ 重要 <section> 地標命名:需要支援無障礙快速跳轉的核心主題 <section>,已透過 aria-labelledby 綁定其內部標題之 id。
  • ☐ 頂層地標邊界清晰:全頁僅有 1 個可見的 <main>,且全站共用的 <header>、<aside>(側邊欄)、<footer> 皆位於 <main> 外部。

七、 參考資料與延伸閱讀

發表迴響