自定義 UI 的隱藏複雜性:為什麼你應該使用語義化 HTML 按鈕
自定義 UI 的隱藏複雜性:為什麼你應該使用語義化 HTML 按鈕
從頭開始重新建立一個原生 HTML 按鈕是一項西西弗斯式的苦差事,因為一個簡單的 <button> 元素封裝了數十年的無障礙標準、瀏覽器行為和作業系統整合。
原生按鈕的要求
要真正取代原生按鈕,自定義組件必須滿足一組嚴格的 UX「法律」和無障礙要求。根據 MDN、W3C ARIA 規範和 WCAG 2.2,一個功能完備的按鈕必須:
- 角色與標籤: 擁有
button角色和清晰的無障礙標籤 (WCAG SC 4.1.2, 1.3.1)。 - 焦點管理: 具備鍵盤焦點功能,且在獲得焦點時是可見的 (WCAG SC 2.4.3, 2.4.7)。
- 輸入模式: 可透過滑鼠點擊、觸控、手寫筆和其他指向裝置啟動。
- 鍵盤互動: 在獲得焦點時,特別是透過 Space 和 Enter 鍵啟動 (WCAG SC 2.1.1)。
- 表單整合: 支援
type(submit,reset,button),參與表單驗證,並處理如formaction,formmethod, 和formtarget等屬性 (WCAG SC 3.3.1)。 - 狀態管理: 支援如
disabled等狀態 (WCAG SC 4.1.2)。 - 現代 API 支援: 與較新的瀏覽器功能整合,例如 Popover API 或 Invoker Commands API。
實作落差:從標記到 500 行程式碼
從頭開始建立按鈕揭示了簡單的 HTML 標籤與為了讓所有使用者都能正常運作所需的底層邏輯之間巨大的落差。
1. 無障礙與焦點
預設情況下,自定義標籤(例如 <sagan-button>)會被視為 <span>。為了讓它成為一個按鈕,開發者必須手動添加 role="button" 和 tabindex="0" 以確保它出現在無障礙樹(accessibility tree)和頁面的 Tab 順序中。對於圖示按鈕,還需要額外的工作來使用 aria-hidden="true" 隱藏裝飾性的表情符號或圖示,並提供描述性的 aria-label 以避免螢幕閱讀器朗讀表情符號的字面名稱。
2. 事件處理與模式
原生按鈕會自動處理各種輸入方法。自定義實作必須明確監聽 mouseup, touchend, 和 onpointerup 以涵蓋滑鼠、觸控和手寫筆互動。此外,鍵盤無障礙性需要為 keydown (Enter 鍵) 和 keyup (Space 鍵) 提供獨立的邏輯,以符合原生瀏覽器的預期。
3. 表單關聯與驗證
原生按鈕最複雜的面向之一是它與 HTML 表單的關係。為了複製這種行為,自定義元素必須設置 static formAssociated = true 並為包括 type, form, formaction, formmethod, formenctype, formnovalidate, formtarget, name, 和 value 在內的屬性實作一組龐大的 getter 和 setter。
它還必須與 Validation API 整合,實作如 checkValidity() 和 reportValidity() 等方法,並透過 ElementInternals 管理 validity 狀態。
4. 狀態與事件順序
為了防止自定義按鈕行為異常,開發者必須封裝 addEventListener 方法。這能確保內部邏輯(例如設置「啟動」狀態或檢查按鈕是否已禁用)相對於使用者定義的事件監聽器以正確的順序執行。如果沒有這點,在點擊事件上調用 preventDefault() 可能無法停止按鈕的預設行為,如果內部處理程序註冊不正確。
專家見解綜述
開發者之間的討論強調了追求自定義組件的趨勢往往優先考慮美學而非可用性與無障礙性。
- 可用性 vs. 美學: 有人認為,業界已將功能強大、高對比度的原生組件替換成了「扁平化廢話」,這些組件通常使用起來更慢且不夠直觀。
- 「無障礙性陷阱」: 有報導指出,公司因無障礙性不合規而被起訴,最後卻只能靠顧問「拯救」——這些顧問只是簡單地移除複雜的 ARIA 標籤並將網站恢復為標準的語義化 HTML。
- AI 的角色: 雖然有人認為 AI 現在可以在幾分鐘內生成自定義組件所需的樣板程式碼,但其他人警告,AI 經常是在無障礙性差的程式碼上進行訓練的,這可能會大規模地傳播不良的無障礙模式。
- 缺失的原生元素: 一個常見的反駁觀點是,自定義組件有時是必要的,因為原生 HTML 缺乏某些複雜的元素,例如具有伺服器端過濾功能的 combobox。
結論:語義化 HTML 的重要性
從頭開始重新建立一個按鈕需要將近 500 行 JavaScript 來實現僅僅是單個 <button> 標籤所提供功能的一小部分。維護負擔、因無障礙性失敗而面臨法律訴訟的風險,以及使用者體驗的退化,使得自定義構建的基礎 UI 元素成為一個低效的選擇。除非針對特定模式不存在對應的原生元素,否則語義化 HTML 仍然是網頁開發的金科玉律。