使用 Tabindex

使用 Tabindex 修改 DOM 順序

Dave Gash
Dave Gash
Meggin Kearney
Meggin Kearney

原生元素 DOM 位置提供的預設分頁順序相當方便,但有時您或許會想修改分頁順序,而在 HTML 中實際移動元素未必是最佳或可行的解決方案。在這種情況下,您可以使用 tabindex HTML 屬性明確設定元素的分頁位置。

瀏覽器支援

  • 1
  • 12
  • 1.5
  • 最多 4 個

資料來源

tabindex 可套用至任何元素,但不一定適用於所有元素,且會採用一個整數值範圍。透過 tabindex,您可以為可聚焦的網頁元素指定明確的順序、將不可聚焦的元素插入分頁順序,並從分頁順序中移除元素。例如:

tabindex="0":在自然的定位點順序中插入元素。按下 Tab 鍵就能聚焦元素,呼叫其 focus() 方法則可聚焦元素

<custom-button tabindex="0">Press Tab to Focus Me!</custom-button>

按下 Tab 鍵即可專心!

tabindex="-1":從自然分頁標籤順序中移除元素,但呼叫其 focus() 方法仍可聚焦該元素

// TODO: DevSite - Code sample removed as it used inline event handlers

// 待辦事項:DevSite - 因使用內嵌事件處理常式而移除的程式碼範例

tabindex="5":如果分頁標籤索引數量大於 0,系統就會將元素跳至自然分頁順序的前方。如果多個定位索引值大於 0,分頁順序就會從大於 0 的最低值開始,並依此往上排序。使用大於 0 的定位索引會視為反模式

<button>I should be first</button>
<button>And I should be second</button>
<button tabindex="5">But I jumped to the front!</button>

在標頭、圖片或文章標題等非輸入元素中更是如此。在這些類型元素中新增 tabindex 會產生反效果。如果可以,最好整理原始碼,讓 DOM 序列提供邏輯分頁順序。如果您使用 tabindex,請將其限制為自訂互動控制項,例如按鈕、分頁、下拉式選單和文字欄位,也就是使用者可能會希望輸入的元素。

您不必擔心螢幕閱讀器使用者缺少重要內容,因為其沒有 tabindex。即使內容非常重要 (例如圖片),如果使用者無法與其互動,根本沒有理由將該內容設為可聚焦。只要您提供適當的 alt 屬性支援,螢幕閱讀器使用者仍能瞭解圖片的內容,我們稍後會說明。

在網頁層級管理焦點

在以下情況中,tabindex 不僅實用,也是一種必要。那麼,您可以建構包含不同內容區段的完善單一網頁,而不是所有內容區段同時顯示。在這類頁面中,點選導覽連結可能會變更顯示內容,而不重新整理頁面。

發生這種情況時,您可能會識別所選內容區域,為其提供 -1 的 tabindex,這樣便不要以自然分頁順序顯示,並呼叫其 focus 方法。這項技術稱為「管理焦點」,可讓使用者感知的背景資訊與網站的視覺內容保持同步。

管理元件中的焦點

在頁面上變更內容時管理焦點很重要,但有時需要在控制層級管理焦點 (例如建構自訂元件時)。

我們來看看原生 select 元素。可接收基本焦點,但一旦取得,您就可以使用方向鍵顯示其他功能 (可選取的選項)。如要建構自訂 select 元素,建議您公開這些相同類型的行為,讓主要仰賴鍵盤的使用者仍可與控制項互動。

<!-- Focus the element using Tab and use the up/down arrow keys to navigate -->
<select>
    <option>Aisle seat</option>
    <option>Window seat</option>
    <option>No preference</option>
</select>

瞭解要實作的鍵盤行為並不容易,但您可以參考一些實用文件。無障礙網際網路應用程式 (ARIA) 編寫做法指南列出元件類型,以及這類元件支援的鍵盤動作類型。我們稍後會更詳細地介紹 ARIA,但現在我們先使用指南,協助我們將鍵盤支援加入新的元件。

也許您正在處理一些與一組圓形按鈕類似的新自訂元素,但有獨特的外觀和行為。

<radio-group>
    <radio-button>Water</radio-button>
    <radio-button>Coffee</radio-button>
    <radio-button>Tea</radio-button>
    <radio-button>Cola</radio-button>
    <radio-button>Ginger Ale</radio-button>
</radio-group>

如要判斷所需的鍵盤支援類型,請參閱 ARIA 編寫做法指南。第 2 節包含設計模式清單,該清單是無線電群組的特性表格,也就是與新元素最相符的現有元件。

如表格所示,系統可能需要支援的常見鍵盤行為之一就是向上/向下/向左/向右鍵。如要將這個行為新增至新元件,我們會使用「核准定位索引」技術。

圓形按鈕的 W3C 規格摘錄。

旋轉分頁索引的運作方式是將所有子項的 tabindex 設為 -1 (目前使用中的子項除外)。

<radio-group>
    <radio-button tabindex="0">Water</radio-button>
    <radio-button tabindex="-1">Coffee</radio-button>
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

接著,此元件會使用鍵盤事件監聽器,判斷使用者按下哪個按鍵。如果發生這種情況,該元件會將先前聚焦的子項 tabindex 設為 -1、將待聚焦的子項 tabindex 設為 0,並對其呼叫聚焦方法。

<radio-group>
    // Assuming the user pressed the down arrow, we'll focus the next available child
    <radio-button tabindex="-1">Water</radio-button>
    <radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

當使用者到達最後一個 (或第一個,取決於他們移動焦點的方向) 的子項時,就會循環顯示第一個 (或最後一個) 子項。

您可以將完成的範例試用如下。在開發人員工具中檢查元素,觀察分頁索引從某個無線電移至下一個無線電。

咖啡 Tea 可樂 Ginger Ale

// 待辦事項:DevSite - 因使用內嵌事件處理常式而移除的程式碼範例

您可以在 GitHub 上查看此元素的完整原始碼

視窗和鍵盤陷阱

有時在管理焦點時,您可能會遇到難以離開的情況。假設有自動完成小工具,嘗試管理焦點及擷取分頁行為,但會防止使用者離開小工具,直到小工具完成為止。這就是所謂的鍵盤陷阱,可能會讓使用者感到非常困擾。Web AIM 檢查清單的第 2.1.2 節已解決這個問題,指出鍵盤焦點一律不得鎖定或影響到單一頁面元素。讓使用者只要用鍵盤就能來回瀏覽所有頁面元素。

奇怪的是,有時這個行為確實符合預期,例如強制回應視窗。一般而言,在顯示互動視窗時,您不希望使用者存取該互動視窗背後的內容。您可以新增重疊元素,以視覺化的方式蓋住頁面,但這樣並不會阻止鍵盤焦點意外離開視窗之外。

互動視窗,要求使用者儲存工作。

在這類情況下,您可以實作臨時鍵盤陷阱,確保只有在顯示互動視窗時能捕捉焦點,然後在關閉互動視窗時,將焦點還原到先前聚焦的項目。

有一些提案 (包括 <dialog> 元素) 可讓開發人員更輕鬆地達成此目標,但這些提案目前尚未支援廣泛的瀏覽器。

如要進一步瞭解 <dialog>,請參閱這篇 MDN 文章,以及這個互動視窗範例

假設這是由 div 代表的強制回應對話方塊,其中包含幾個元素,以及另一個代表背景重疊的 div。以下逐步說明在這種情況下實作暫時性鍵盤繞圈的必要基本步驟。

  1. 使用 document.querySelector 即可選取互動視窗和疊加層 div,並儲存其參照。
  2. 互動視窗開啟時,儲存互動視窗開啟時聚焦元素的參照,以便您將焦點回傳至該元素。
  3. 在互動視窗開啟時,使用 keydown 事件監聽器擷取按鍵。您也可以監聽背景重疊的點擊,並在使用者點擊背景重疊時關閉互動視窗。
  4. 接著,在互動視窗中取得可聚焦元素集合。第一個和最後一個可聚焦元素將做為「前段」,讓您知道何時要將焦點向前或向後轉動,以便停留在互動視窗中。
  5. 顯示互動視窗,並將焦點移至第一個可聚焦的元素。
  6. 當使用者按下 TabShift+Tab 時,視需要向前或向後移動焦點,在最後一個或第一個元素上輪流。
  7. 當使用者按下 Esc 時,關閉互動視窗。這種做法非常實用,可讓使用者在不搜尋特定關閉按鈕的情況下關閉互動視窗,而且即使是使用滑鼠的使用者也能因此受益。
  8. 關閉互動視窗後,請隱藏該互動視窗和背景重疊,然後將焦點還原為先前儲存的元素。

這項程序提供可用且不會讓人感到不悅的強制回應視窗,讓所有人都能有效使用。

如需詳細資訊,請查看這個程式碼範例,並在完整頁面中查看即時範例。