支援鍵盤導航的 JavaScript 元件
Web 應用程式通常使用 JavaScript 來模擬桌面元件,例如選單、樹形檢視、富文字欄位和選項卡面板。這些元件通常由 <div> 和 <span> 元素組成,它們本身並不提供與其桌面對應元件相同的鍵盤功能。本文件介紹了使 JavaScript 元件可以透過鍵盤訪問的技術。
使用 tabindex
預設情況下,當用戶使用 Tab 鍵瀏覽網頁時,只有互動式元素(如連結、表單控制元件)會獲得焦點。使用 tabindex 全域性屬性,作者也可以使其他元素可聚焦。當設定為 0 時,該元素可以透過鍵盤和指令碼獲得焦點。當設定為 -1 時,該元素可以透過指令碼獲得焦點,但不會成為鍵盤焦點順序的一部分。
使用鍵盤時元素獲得焦點的順序預設情況下是源順序。在特殊情況下,作者可能希望重新定義順序。為此,作者可以將 tabindex 設定為任何正數。
警告:避免為 tabindex 使用正值。具有正 tabindex 的元素放在頁面上預設互動式元素之前,這意味著頁面作者在使用一個或多個正 tabindex 值時,必須為頁面上的所有可聚焦元素設定(並維護)tabindex 值。
下表描述了現代瀏覽器中 tabindex 的行為
tabindex 屬性 |
可透過滑鼠或 JavaScript(透過 element.focus())獲得焦點 |
可透過 Tab 鍵導航 |
|---|---|---|
| 不存在 | 遵循元素的平臺約定(表單控制元件、連結等為是)。 | 遵循元素的平臺約定。 |
負數(即 tabindex="-1") |
是 | 否;作者必須在響應箭頭鍵或其他按鍵時,使用 focus() 使元素獲得焦點。 |
零(即 tabindex="0") |
是 | 在文件中元素位置相關的 Tab 順序中(請注意,像 <a> 這樣的互動式元素預設具有此行為,它們不需要此屬性)。 |
正數(例如 tabindex="33") |
是 | tabindex 值決定此元素在 Tab 順序中的位置:較小的值會使元素在 Tab 順序中比較大的值更早出現(例如,tabindex="7" 將位於 tabindex="11" 之前)。 |
非原生控制元件
分組控制元件
對於選單、選項卡列表、網格或樹形檢視等分組元件,父元素應位於 Tab 順序中(tabindex="0"),並且每個子元素選擇/選項卡/單元格/行應從 Tab 順序中移除(tabindex="-1")。使用者應該能夠使用箭頭鍵導航子元素。(有關通常預期用於典型元件的鍵盤支援的完整描述,請參閱 WAI-ARIA 創作實踐)。
下面的示例展示了這種技術如何與巢狀選單控制元件一起使用。一旦鍵盤焦點落在包含 <ul> 元素上,JavaScript 開發人員必須以程式設計方式管理焦點並響應箭頭鍵。有關在元件內管理焦點的技術,請參閱下面的“管理組內的焦點”。
<ul id="mb1" tabindex="0">
<li id="mb1_menu1" tabindex="-1">
Font
<ul id="fontMenu" title="Font" tabindex="-1">
<li id="sans-serif" tabindex="-1">Sans-serif</li>
<li id="serif" tabindex="-1">Serif</li>
<li id="monospace" tabindex="-1">Monospace</li>
<li id="fantasy" tabindex="-1">Fantasy</li>
</ul>
</li>
<li id="mb1_menu2" tabindex="-1">
Style
<ul id="styleMenu" title="Style" tabindex="-1">
<li id="italic" tabindex="-1">Italics</li>
<li id="bold" tabindex="-1">Bold</li>
<li id="underline" tabindex="-1">Underlined</li>
</ul>
</li>
<li id="mb1_menu3" tabindex="-1">
Justification
<ul id="justificationMenu" title="Justification" tabindex="-1">
<li id="left" tabindex="-1">Left</li>
<li id="center" tabindex="-1">Centered</li>
<li id="right" tabindex="-1">Right</li>
<li id="justify" tabindex="-1">Justify</li>
</ul>
</li>
</ul>
停用控制元件
當自定義控制元件被停用時,透過設定 tabindex="-1" 將其從 Tab 順序中移除。請注意,分組元件中的停用項(例如選單中的選單項)應能夠繼續使用箭頭鍵進行導航。
管理組內的焦點
當用戶從元件切換到其他位置再返回時,焦點應返回到具有焦點的特定元素,例如樹項或網格單元格。有兩種技術可以實現這一點
- 遊動
tabindex:以程式設計方式移動焦點 aria-activedescendant:管理“虛擬”焦點
技術 1:遊動 tabindex
將聚焦元素的 tabindex 設定為“0”可確保如果使用者從元件切換到其他位置再返回,組內的選中項將保留焦點。請注意,將 tabindex 更新為“0”也需要將先前選中的項更新為 tabindex="-1"。此技術涉及以程式設計方式響應按鍵事件移動焦點並更新 tabindex 以反映當前聚焦的項。為此
為組中的每個元素繫結一個鍵盤按下處理程式,當使用箭頭鍵移動到另一個元素時
- 以程式設計方式將焦點應用於新元素,
- 將聚焦元素的
tabindex更新為“0”,以及 - 將先前聚焦元素的
tabindex更新為“-1”。
這是一個使用此技術的WAI-ARIA 樹檢視示例。
提示
使用element.focus()設定焦點
不要使用createEvent()、initEvent()和dispatchEvent()將焦點發送到元素。DOM 焦點事件僅被視為資訊性事件:在某個元素獲得焦點後由系統生成,但實際上不用於設定焦點。請改用element.focus()。
使用onfocus跟蹤當前焦點
不要假設所有焦點更改都來自鍵盤和滑鼠事件:螢幕閱讀器等輔助技術可以將焦點設定為任何可聚焦元素。請改用onfocus和onblur跟蹤焦點。
onfocus和onblur現在可以與每個元素一起使用。沒有標準的DOM介面來獲取當前文件焦點。如果要跟蹤焦點狀態,可以使用document.activeElement獲取活動元素。您還可以使用document.hasFocus來確保當前文件焦點。
技術 2:aria-activedescendant
此技術涉及將單個事件處理程式繫結到容器小部件,並使用aria-activedescendant跟蹤“虛擬”焦點。(有關 ARIA 的更多資訊,請參閱此可訪問 Web 應用程式和小部件概述。)
aria-activedescendant屬性標識當前具有虛擬焦點的後代元素的 ID。容器上的事件處理程式必須響應鍵和滑鼠事件,方法是更新aria-activedescendant的值並確保當前專案以適當的方式設定樣式(例如,使用邊框或背景顏色)。
通用指南
使用onkeydown捕獲鍵盤事件,而不是onkeypress
IE 不會為非字母數字鍵觸發keypress事件。請改用onkeydown。
確保鍵盤和滑鼠產生相同的體驗
為了確保使用者體驗在任何輸入裝置下都保持一致,鍵盤和滑鼠事件處理程式應在適當的情況下共享程式碼。例如,當用戶使用箭頭鍵導航時更新tabindex或樣式的程式碼也應由滑鼠單擊處理程式使用以產生相同的更改。
確保可以使用鍵盤啟用元素
為了確保可以使用鍵盤啟用元素,繫結到滑鼠事件的任何處理程式也應繫結到鍵盤事件。例如,為了確保 Enter 鍵可以啟用元素,如果您有onclick="doSomething()",則還應將doSomething()繫結到鍵盤按下事件:onkeydown="event.code === "Enter" && doSomething();"。
始終為tabindex="-1"的專案和以程式設計方式接收焦點的元素繪製焦點
IE 不會自動為以程式設計方式接收焦點的專案繪製焦點輪廓。在更改背景顏色(例如this.style.backgroundColor = "gray";)或新增點狀邊框(例如this.style.border = "1px dotted invert")之間進行選擇。在點狀邊框的情況下,您需要確保這些元素最初具有不可見的 1px 邊框,以便在應用邊框樣式時元素不會增長(邊框佔用空間,而 IE 沒有實現 CSS 輪廓)。
防止使用的鍵盤事件執行瀏覽器功能
如果您的視窗小部件處理鍵盤事件,請使用事件處理程式的返回值阻止瀏覽器也處理它(例如,響應箭頭鍵滾動)。如果您的事件處理程式返回false,則該事件將不會傳播到您的處理程式之外。
例如
<span tabindex="-1" onkeydown="return handleKeyDown();">…</span>
如果handleKeyDown()返回false,則該事件將被消耗,阻止瀏覽器根據按鍵執行任何操作。
目前不要依賴於按鍵重複的一致行為
不幸的是,onkeydown可能會或可能不會重複,具體取決於您正在執行的瀏覽器和作業系統。