網頁元件簡介

網頁元件包括自訂元素、Shadow DOM 和 HTML 範本,是可重複使用、與架構無關的元件平台原始物件,其標記和樣式會從文件中封裝。可用於設計系統、可嵌入的小工具和獨立 UI。

以下規則適用於所有層級。擷取手邊工作的特定指南;每份指南都會重述所需的背景資訊,並記錄專屬的 API 和陷阱。

決定是否需要自訂元素

只有在需要封裝行為、生命週期或可重複使用的 JS 支援 API 時,才需要使用自訂元素。在下列情況下,請不要建立:

  • 使用 CSS 的純 HTML 元素即可。與重新實作相比,設定樣式的 <button> 或 <details> 更容易存取,且成本更低。
  • 這個項目純粹是呈現內容,不具任何行為。原生元素上的類別效能較佳,且可使用 @layer 或 @scope 設定範圍。
  • 您只需要在伺服器上設定樣式範圍,不需互動;範圍樣式表或宣告式 Shadow DOM (不需升級) 可能就足夠。

重建原生語意 (重新建立焦點、啟用和 ARIA 的自訂 <my-button>) 是最常見的誤用方式:只有在重複使用原生元素時,才能免費沿用平台的無障礙功能。如果需要 <my-button> 樣式的包裝函式 (通常用於共用樣式掛鉤、額外標記或原生元素無法表達的行為),請包裝實際的 <button>,而不是重新實作 (請參閱「設定網頁元件樣式」,瞭解如何將樣式轉送至內部原生元素)。

測試的重點在於您是否需要封裝狀態、可編寫指令碼的 API,或原生元素無法表達的行為,而不僅僅是不同的外觀。按讚/加入收藏切換鈕符合條件:它會攜帶鎖定的網域狀態,將該狀態公開為周圍網頁的樣式掛鉤,並調度自己的 change 事件,這些都是樣式化 <button> 無法提供的。如果按鈕只在按下時變色,則不符合條件:請使用 <button> + CSS。建構時,請視情況使用自訂狀態或屬性建立狀態模型 (請參閱「自訂元素」)。

根據程式碼集選擇工具

某個項目是否應為自訂元素,取決於專案已使用的項目。代理程式往往會過度抽象化,並急於尋找新元素。如有疑慮,通常應選擇較輕量的選項 (原生元素、CSS、伺服器範本),日後如果實際需要重複使用或行為,再升級為自訂元素。經驗法則 (大致依優先順序排列):

  • 程式碼集已有元件模型 (React、Vue、Svelte 等)。預設使用該架構的元件做為應用程式內 UI。只有在必須逸出或超出框架時,才使用自訂元素:在應用程式或框架之間共用的設計系統原始元素、放入框架無法控制的標記中的小工具,或必須以純 HTML 形式運作的輸出內容 (電子郵件、CMS、SSR 片段)。請勿為一般應用程式內檢視區塊,建立平行元件系統。
  • 沒有工具,大多是靜態標記。建議使用純 HTML + CSS,或伺服器範本/部分範本。只有在標記上確實需要行為、生命週期或 JS 支援的 API 時,自訂元素才有用處,而不只是為了共用標記,伺服器包含或 <template> 可以在不提供任何 JS 的情況下執行。
  • 具有互動島的靜態網站產生器。以靜態方式轉譯標記,並保留自訂元素用於互動部分。如果是「大量標記,少量互動」,請將標記保留在 Light DOM (或宣告式 Shadow DOM) 中,並讓小型自訂元素逐步強化,而不是從 JS 重新轉譯所有內容。
  • 你可以進一步推動內建元素。盡可能使用原生元素 (CSS、一些事件監聽器、偶爾使用虛擬元素),通常比使用自訂元素更好,因為您可以免費保留平台的無障礙功能和行為。當解決方法無法再維護時,請改用自訂元素,因為您會與元素的內建行為發生衝突,或編寫體驗會比乾淨的元件 API 更差。內建元素需要一點 JS,本身並不是替換它的理由。

跨領域規則

以下所有指南都適用這些原則:

  • 必要:標記名稱必須採用 kebab case,且至少包含一個連字號 (例如 my-element)。這是區分自訂元素與目前和未來內建元素的依據。
  • 必要:在建構函式中,請先呼叫 super(),再觸控 this;在讀取或寫入 this 擲回的任何陳述式之後呼叫。
  • 強制:在 Shadow 範本中使用語意元素 (<button>、<nav>、<ul>)。Shadow Tree 中大多數無障礙功能失敗的原因,都是非語意標記;插槽不會變更其投影的角色。
  • 必要:ARIA id 參照 (aria-labelledby、aria-describedby、aria-controls) 不得跨越陰影邊界;參照元素和指向的 id 必須位於同一個樹狀結構中。
  • 建議使用 attachShadow({ mode: 'open' }),讓開發人員工具、網頁指令碼和伺服器凍結狀態還原功能可以連上 element.shadowRoot。只有在必須對網頁指令碼隱藏內部結構時,才使用 'closed'。
  • 避免使用自訂內建元素 (extends HTMLButtonElement 搭配 is="…");Safari 已永久拒絕提供這類元素。

用途指南矩陣

找出工作並擷取指南:

如果需要… 擷取
定義具有行為和生命週期的新語意標記 自訂元素
將樣式和標記限定在元件範圍內,並將消費者內容投射到元件中 Shadow DOM、範本和版位
在伺服器上算繪元件的 Shadow Tree (SSR),避免未套用樣式的內容閃爍 預先算繪自訂元素
跨陰影邊界設定樣式 (主題設定、::part、自訂屬性) 設定網頁元件樣式
將自訂控制項的值提交至周圍的 <form> 表單關聯自訂元素
讓自訂元素符合無障礙設計 (角色、焦點、跨 Shadow Root 的 ARIA) 無障礙網頁元件