37. 全域屬性 (Global Attributes)

全域屬性是可以用於所有 HTML 元素的屬性,但實際效果取決於元素及使用情境。

它們可以識別元素、支援樣式及程式碼操作、描述語言,以及控制部分互動行為。

<p
  id="course-summary"
  class="intro"
  lang="zh-Hant-HK"
  data-course-id="html-basics"
>
  學習建立符合無障礙需要的 HTML 網頁。
</p>

屬性是全域的,不代表它適合用於每個元素。

應根據用途選擇屬性,不要只因為可以使用就加入它們。

37.1 常見全域屬性

以下表格介紹常見全域屬性,並非完整清單。

屬性用途
id在文件中唯一識別元素
class指派可重用的類別名稱
style提供行內 CSS 宣告
title提供補充提示資訊
lang識別自然語言
dir指定文字方向
data-*儲存應用程式專用資料
hidden將內容標示為隱藏
inert令子樹無法互動
tabindex控制焦點參與方式
contenteditable控制內容是否可以編輯
spellcheck要求拼字及文法檢查
translate表示內容是否應翻譯
draggable控制是否參與原生拖曳
accesskey建議鍵盤快捷鍵
autofocus在適用情況下要求初始焦點
popover讓元素可以作為彈出內容顯示

其他全域屬性支援網頁元件、結構化中繼資料及虛擬鍵盤行為等專門功能。

37.2 使用 id 提供唯一識別碼

使用 id 為元素提供唯一識別碼:

<h2 id="course-details">課程詳情</h2>

ID 可以用於:

  • 片段連結。
  • CSS 選擇器。
  • JavaScript。
  • 標籤及無障礙關聯。
<a href="#course-details">跳至課程詳情</a>
#course-details {
  scroll-margin-block-start: 1rem;
}
const heading = document.getElementById("course-details");

ID 不能為空,也不能包含 ASCII 空白字元,並且必須在所屬文件中保持唯一。

HTML 允許部分在 CSS 選擇器中需要轉義的 ID 值。使用 course-details 等簡單、具描述性的值,可以避免不必要的複雜處理。

不要依靠 ID 自動成為 JavaScript 全域變數。應明確選取元素。

37.3 使用 class 建立可重用群組

使用 class 指派一個或多個以空白分隔的類別名稱:

<section class="card featured">
  <h2>HTML 入門</h2>
</section>

多個元素可以共用類別:

.card {
  padding: 1rem;
  border: 1px solid #767676;
}

.featured {
  background: #eaf2f8;
}

與 ID 不同,類別名稱不需要唯一。

JavaScript 可以透過 classList 管理類別:

const card = document.querySelector(".card");

card.classList.add("selected");
card.classList.remove("featured");
card.classList.toggle("expanded");

應選擇能傳達有用角色或狀態的類別名稱。例如,warning 通常比 red-text 更容易維護。

類別名稱本身不會建立語意或行為。

37.4 使用 style 提供行內樣式

style 屬性包含 CSS 宣告:

<p style="color: #005ea8; font-weight: 700;">
  現正接受報名。
</p>

它不包含選擇器或完整樣式表。

可重用的樣式應優先使用類別及樣式表:

<p class="registration-notice">現正接受報名。</p>
.registration-notice {
  color: #005ea8;
  font-weight: 700;
}

行內樣式可以用於元素專用的值,但過度使用會增加維護難度。

它們仍然受 CSS 階層規則及適用的內容安全政策限制。

37.5 使用 title 提供提示資訊

title 提供額外提示資訊:

<abbr title="Hypertext Markup Language">HTML</abbr>

瀏覽器通常會在指標停留時,以工具提示顯示它。

不過,觸控、鍵盤導覽及輔助技術不一定能一致地取得這些資訊。

不要只在 title 中提供重要指引或標籤。

例如,表單應提供可見標籤:

<label for="email">電郵地址</label>
<input id="email" type="email">

title 屬性與文件的 <title> 元素不同。

對 iframe 而言,具描述性的 title 在識別嵌入框架方面具有重要作用,詳見第 29 章。

37.6 語言與方向

使用 lang 識別自然語言:

<p lang="zh-Hant-HK">歡迎參加課程。</p>

使用 dir 指定文字方向:

<p lang="ar" dir="rtl">مرحبًا بكم.</p>

常見方向值包括:

  • ltr:由左至右。
  • rtl:由右至左。
  • auto:根據內容判斷方向。

語言與方向不同。設定 lang="ar" 不會自動宣告由右至左的方向。

方向未知的使用者文字:

<p dir="auto">使用者提供的文字會顯示在這裏。</p>

語言標籤及語言繼承詳見第 30 章。

37.7 使用 data-* 儲存應用程式資料

自訂資料屬性儲存應用程式專用資訊:

<article
  class="course-card"
  data-course-id="html-basics"
  data-level="beginner"
>
  <h2>HTML 基礎</h2>
</article>

JavaScript 可以透過 dataset 存取:

const card = document.querySelector(".course-card");

console.log(card.dataset.courseId);
console.log(card.dataset.level);

以連字號分隔的名稱,會對應至駝峰式命名的屬性:

HTML 屬性JavaScript 屬性
data-course-iddataset.courseId
data-leveldataset.level
data-start-datedataset.startDate

值是字串:

const learners = Number(card.dataset.learners);

重要限制包括:

  • 資料屬性可以公開讀取。
  • 不適合儲存密碼或秘密資訊。
  • 不會自動以無障礙方式提供資訊。
  • 不會驗證儲存的值。

讀者需要的資訊,應透過可見文字及適當語意提供。

37.8 使用 hidden 隱藏內容

一般 hidden 狀態表示內容不應呈現:

<p hidden>這個訊息目前不會顯示。</p>

通常,它不會被繪製,也不會出現在無障礙樹中。

顯示內容:

const message = document.getElementById("message");
message.hidden = false;

不要使用 hidden="false" 顯示內容:

<!-- 仍然要求隱藏狀態。 -->
<p hidden="false">這不是可見狀態的宣告。</p>

應移除屬性,或將 DOM 屬性設為 false。

找到後才顯示

HTML 也定義以下形式:

<section hidden="until-found">
  <h2>補充資訊</h2>
  <p>找到時可以顯示的詳細內容。</p>
</section>

支援的瀏覽器可以透過頁內搜尋或片段導覽顯示這些內容。它的版面行為與一般隱藏內容不同,應測試支援情況。

hidden 不是存取控制。內容仍然存在於文件原始碼中,隱藏容器內的程式碼也不會自動停止執行。

CSS 也可能覆蓋預期的隱藏行為,因此應檢查互相衝突的顯示規則。

37.9 使用 inert 建立不可互動的子樹

inert 令元素及其後代無法互動:

<section inert>
  <h2>暫時不可用的面板</h2>
  <button type="button">提交</button>
</section>

inert 內容不能取得焦點或接受使用者互動,也不會提供給無障礙 API。

與一般隱藏內容不同,它可以繼續在畫面上顯示。

如果使用者需要知道區段不可用,應提供相應視覺樣式。

不要混淆 inert 與:

  • disabled:適用於支援的控制元素。
  • aria-disabled:傳達狀態,但不實作停用行為。
  • aria-hidden:本身不會阻止鍵盤焦點。

將目前具有焦點的區域設為 inert 前,應先管理焦點。

37.10 使用 contenteditable 編輯內容

contenteditable 允許使用者編輯元素內容:

<div contenteditable="true">
  編輯這段文字。
</div>

重要值包括:

值意思
true 或空值啟用編輯
false停用該元素的編輯功能
plaintext-only啟用純文字編輯,不保留豐富文字格式

屬性不存在或值無效時,編輯行為會繼承。

contenteditable 是列舉屬性,不是布林屬性。它的值具有意義。

一般表單輸入應優先使用 <input> 或 <textarea>。可編輯容器不會自動提供:

  • 表單控制名稱及提交值。
  • 可見標籤。
  • 儲存功能。
  • 驗證。
  • 完整的無障礙編輯器介面。

應將編輯後的內容視為不可信輸入。豐富文字編輯不會自動清理 HTML,確保它適合安全儲存或日後呈現。

37.11 檢查、翻譯與拖曳

以下全域屬性提供額外指示:

<textarea spellcheck="true"></textarea>

<code translate="no">index.html</code>

<img
  src="images/course-icon.svg"
  alt="HTML 課程"
  draggable="false"
>
屬性常見值用途
spellchecktrue、false要求拼字及文法檢查
translateyes、no表示內容是否應翻譯
draggabletrue、false控制原生拖曳

支援情況取決於瀏覽器及相關工具。

這些屬性不是可以互換的布林旗標。例如,應寫 draggable="true",而不是只加入沒有值的 draggable 屬性。

設定 draggable="true" 也不會實作完整的無障礙拖放介面。應提供可用鍵盤操作的替代方式。

37.12 焦點與鍵盤屬性

部分全域屬性會影響鍵盤操作:

屬性建議
tabindex優先使用 0 和 -1,避免正值
autofocus小心使用,避免意外移動焦點
accesskey不要將它作為唯一快捷鍵機制

可以這樣宣告存取鍵:

<button type="button" accesskey="s">儲存</button>

實際啟動按鍵組合因平台及瀏覽器而異,也可能與其他快捷鍵衝突。

autofocus 在適用的載入或開啟情況下要求焦點。如果自動聚焦會略過重要背景資訊,或意外開啟流動裝置鍵盤,應避免使用。

焦點次序及焦點管理詳見第 36 章。

37.13 彈出內容與專門屬性

全域屬性 popover 可以讓元素作為彈出內容顯示:

<button type="button" popovertarget="course-help">
  顯示課程說明
</button>

<div id="course-help" popover>
  <p>先從入門課程開始。</p>
</div>

在這個例子中:

  • popover 是全域屬性。
  • popovertarget 是啟動按鈕支援的屬性。
  • 彈出內容不是模態介面,不會自動令背景變成 inert。

其他專門全域屬性包括:

  • slot:指定內容放入網頁元件的哪個插槽。
  • part:提供 shadow DOM 樣式存取點。
  • inputmode:建議虛擬鍵盤配置。
  • enterkeyhint:建議 Enter 鍵的標籤或操作。
  • itemscope 和 itemprop 等微資料屬性。

這些功能需要各自的實作決策。例如,inputmode="numeric" 建議數字鍵盤,但不會驗證輸入是否為數字。

37.14 布林屬性與列舉屬性

不同屬性以不同方式解讀值。

布林屬性只要存在就會啟用:

<section inert>
  <p>這個區段無法互動。</p>
</section>

寫成 inert="false" 不會將它關閉,應移除屬性。

列舉屬性使用指定的有效值:

<div contenteditable="false">
  這段內容不能編輯。
</div>

不要假設所有全域屬性都使用相同的真假值規則。

ARIA 屬性也有自己的值規則。例如,aria-expanded="false" 表示未展開狀態;它不是 HTML 布林屬性。

37.15 完整範例:全域屬性的應用

以下獨立網頁使用 ID、類別、自訂資料、語言標記及隱藏區段。

原生按鈕顯示補充資訊,並傳達目前的展開狀態。

id: hong-kong-html-global-attributes
name: 全域屬性 — 課程詳情
type: html
content: |-
  <!doctype html>
  <html lang="zh-Hant-HK">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>全域屬性 | 課程詳情</title>
    <style>
      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }

      body {
        margin: 0;
        color: #222;
        background: #f5f7fa;
        font-family: system-ui, sans-serif;
        line-height: 1.8;
      }

      main {
        max-width: 42rem;
        margin-inline: auto;
        padding: 2rem 1rem;
      }

      h1,
      h2 {
        color: #005ea8;
        line-height: 1.4;
      }

      .course-card {
        padding: 1.25rem;
        border: 1px solid #767676;
        border-radius: 0.5rem;
        background: white;
      }

      .course-card > h2 {
        margin-block-start: 0;
      }

      .details {
        margin-block-start: 1rem;
        padding: 1rem;
        border-inline-start: 4px solid #005ea8;
        background: #eaf2f8;
      }

      button {
        padding: 0.6rem 1rem;
        border: 1px solid #005ea8;
        border-radius: 0.3rem;
        color: white;
        background: #005ea8;
        font: inherit;
        cursor: pointer;
      }

      :focus-visible {
        outline: 3px solid #005ea8;
        outline-offset: 3px;
      }

      :lang(en) {
        line-height: 1.7;
      }

      code {
        font-family: ui-monospace, monospace;
      }
    </style>
  </head>
  <body>
    <main>
      <h1>全域屬性的應用</h1>

      <article
        id="html-course"
        class="course-card"
        data-course-id="html-basics"
        aria-labelledby="course-heading"
      >
        <h2 id="course-heading">HTML 基礎</h2>

        <p>
          學習建立結構清晰、符合無障礙需要的網頁。
        </p>

        <p lang="en">
          Learn to structure clear, accessible webpages.
        </p>

        <button
          id="details-toggle"
          type="button"
          aria-expanded="true"
          aria-controls="course-details"
          hidden
        >
          隱藏課程詳情
        </button>

        <div id="course-details" class="details">
          <p>不需要任何 HTML 經驗。</p>
          <p>
            將你的第一個網頁儲存為
            <code translate="no">index.html</code>。
          </p>
        </div>
      </article>

      <p id="course-status" role="status"></p>
    </main>

    <script>
      const card = document.getElementById("html-course");
      const button = document.getElementById("details-toggle");
      const details = document.getElementById("course-details");
      const status = document.getElementById("course-status");

      button.addEventListener("click", () => {
        const opening = details.hidden;

        details.hidden = !opening;
        button.setAttribute("aria-expanded", String(opening));
        button.textContent = opening
          ? "隱藏課程詳情"
          : "顯示課程詳情";

        status.textContent = opening
          ? `已開啟課程 ${card.dataset.courseId} 的詳情。`
          : "課程詳情已關閉。";
      });

      details.hidden = true;
      button.setAttribute("aria-expanded", "false");
      button.textContent = "顯示課程詳情";
      button.hidden = false;
    </script>
  </body>
  </html>

在這個範例中:

  • ID 連接程式碼操作及無障礙關聯。
  • 類別提供可重用的樣式存取點。
  • data-course-id 提供應用程式識別碼。
  • lang 識別英文段落。
  • translate="no" 要求翻譯工具保留檔案名稱。
  • hidden DOM 屬性控制呈現方式。
  • aria-expanded 傳達按鈕目前的狀態。
  • 詳情變更時,程式碼不會主動移動按鈕焦點。

沒有 JavaScript 時,詳情仍然可見。程式碼準備好切換按鈕後,才隱藏詳情並顯示按鈕。

如果只是簡單的展開及收合內容,不需要自訂行為,可以考慮原生 <details> 和 <summary>。

37.16 常見錯誤

錯誤較好的做法
在同一文件重用 ID保持 ID 唯一
以為類別名稱會建立行為另外實作行為
只在 title 提供標籤或指引提供可見且符合無障礙需要的資訊
在 data-* 儲存秘密資訊將屬性視為公開內容
以為資料屬性會自動成為數字轉換並驗證值
使用 inert="false" 關閉 inert 狀態移除布林屬性
使用 hidden="false" 顯示內容移除 hidden,或將 DOM 屬性設為 false
以為隱藏內容是安全的使用適當存取控制
將可編輯 HTML 視為已清理的輸入適當驗證及清理
以為鍵盤提示會執行驗證實作真正的驗證
讓所有元素都可以取得焦點只在有用時加入焦點能力
未理解值規則就加入屬性檢查每個屬性定義的行為

本章總結: 全域屬性提供共用機制,用於識別、樣式、語言、應用程式資料、可見性及互動。它們的效果及值規則各有不同。應有目的地使用、保留原生 HTML 行為,並記住屬性不會自動提供無障礙功能、驗證或安全保護。

Scroll to Top