製作可訪問的對話框
在當今的 Web 應用程序中,對話框與在桌面應用程序中一樣普遍。使用一點 JavaScript 和 CSS 很容易顯示或隱藏覆蓋在頁面上的元素,但很少有人考慮這會如何影響可訪問性。在大多數情況下,這是一場可訪問性災難。輸入焦點未正確處理,屏幕閱讀器無法判斷某些內容已更改。實際上,製作一個完全可訪問的對話框並不難,您只需要了解幾行代碼的重要性即可。
ARIA 角色
如果您希望屏幕閱讀器用戶知道彈出了一個對話框,那麼您需要了解一些有關可訪問富 Internet 應用程序 (ARIA) 角色的知識。詠嘆調
1
角色為 HTML 元素提供額外的語義含義,允許瀏覽器以更具描述性的方式與屏幕閱讀器進行通信。有大量角色會改變屏幕閱讀器感知頁面上不同元素的方式。說到對話框,有兩個有趣的地方:dialog
和 alertdialog
.
在大多數情況下,dialog
是要使用的角色。通過將此設置為 role
的值 元素上的屬性,您正在通知瀏覽器該元素的用途是作為一個對話框。
<div id="my-dialog" role="dialog">
<-- Your dialog code here -->
</div>
當一個角色為 dialog
的元素 變為可見時,瀏覽器會告訴屏幕閱讀器已打開一個新對話框。這讓屏幕閱讀器用戶認識到他們不再處於頁面的常規流程中。
對話框也應該有標籤。您可以使用 aria-label
指定標籤 屬性來指示標籤文本或 aria-labelledby
屬性來指示包含標籤的元素的 ID。下面舉幾個例子:
<div id="my-dialog" role="dialog" aria-label="New Message">
<-- Your dialog code here -->
</div>
<div id="my-dialog" role="dialog" aria-labelledby="dialog-title">
<h3 id="dialog-title">New Message</h3>
<-- Your dialog code here -->
</div>
在第一個示例中,aria-label
屬性用於指定僅由屏幕閱讀器使用的標籤。當對話框沒有可視標籤時,您會希望這樣做。在第二個示例中,aria-labelledby
屬性用於指定包含對話框標籤的元素的 ID。由於對話框具有視覺標籤,因此重用該信息而不是複制它是有意義的。屏幕閱讀器會在顯示對話框時宣布對話框標籤。
alertdialog
的作用 是一種特殊類型的對話,旨在引起用戶的注意。當您嘗試刪除某些內容時,可以將此視為確認對話框。一個 alertdialog
幾乎沒有交互性。它的主要目的是引起用戶的注意,以便執行操作。將其與 dialog
進行比較 ,這可能是用戶輸入信息的區域,例如寫新的電子郵件或即時消息。
當 alertdialog
顯示時,屏幕閱讀器會查找要閱讀的說明。推薦使用aria-describedby
元素來指定應該閱讀哪些文本。類似於 aria-labelledby
, 該屬性是包含要讀取的內容的元素的 ID。如果 aria-describedby
被省略,那麼屏幕閱讀器將嘗試找出代表描述的文本,並且通常會選擇元素中的第一段文本內容。舉個例子:
<div id="my-dialog" role="alertdialog" aria-describedby="dialog-desc">
<p id="dialog-desc">Are you sure you want to delete this message?</p>
<-- Your dialog code here -->
</div>
此示例使用一個元素來包含描述。這樣做可以確保在顯示對話框時讀取正確的文本。
即使您省略了額外的屬性並只使用適當的 role
對於您的對話框,應用程序的可訪問性大大提高。
設置焦點到對話框
創建可訪問對話框的下一部分是管理焦點。顯示對話框時,焦點應放在對話框內部,以便用戶可以繼續使用鍵盤導航。對話焦點的確切位置在很大程度上取決於對話本身的目的。如果您有一個確認對話框,一鍵繼續,一鍵取消,那麼您可能希望默認焦點位於取消按鈕上。如果您有一個用戶應該輸入文本的對話框,那麼您可能希望默認情況下焦點位於文本框上。如果你不知道在哪裡設置焦點,那麼一個很好的起點就是將焦點設置到代表對話框的元素上。
因為大多數時候你會使用 <div>
元素來表示一個對話框,默認情況下你不能設置焦點。相反,您需要通過設置 tabIndex
來啟用對該元素的關注 屬性為-1。這允許您使用 JavaScript 將焦點設置到元素上,但不會將元素插入到正常的 Tab 鍵順序中。這意味著用戶將無法按 Tab 鍵將焦點設置到對話框。您可以直接在 HTML 或 JavaScript 中執行此操作。對於 HTML:
<div id="my-dialog" role="dialog" tabindex="-1" aria-labelledby="dialog-title">
<h3 id="dialog-title">New Message</h3>
<-- Your dialog code here -->
</div>
對於 JavaScript:
var div = document.getElementById("my-dialog");
div.tabIndex = -1;
div.focus();
一次 tabIndex
設置為-1,可以調用focus()
就像任何其他可聚焦元素一樣在元素上。然後用戶可以按 Tab 鍵在對話框中導航。
陷印焦點
對話框的另一個可訪問性問題是確保焦點不會回到對話框之外。在許多情況下,對話框被認為是模態的,因此焦點不應該能夠逃脫對話框。如果對話框是打開的,並且按 Tab 鍵最終將焦點設置在對話框後面,那麼鍵盤用戶很難回到對話框中。因此,最好使用一點 JavaScript 來防止這種情況發生。
該技術背後的基本思想是使用事件捕獲來監聽 focus
事件,Peter-Paul Koch 推廣的一種技術
2
現在大多數 JavaScript 庫都在使用它。自 focus
不會冒泡,您無法在事件流的那一側捕獲它。相反,您可以攔截所有 focus
使用事件捕獲在頁面上的事件。然後,您只需要確定獲得焦點的元素是否在對話框中。如果沒有,請將焦點設置回對話框。代碼很簡單:
document.addEventListener("focus", function(event) {
var dialog = document.getElementById("my-dialog");
if (dialogOpen && !dialog.contains(event.target)) {
event.stopPropagation();
dialog.focus();
}
}, true);
此代碼偵聽 focus
文檔上的事件,以便在目標元素接收到它們之前攔截所有此類事件。假設 dialogOpen
對話框打開時變量設置為 true。當 focus
事件發生時,此函數捕獲事件並檢查對話框是否打開,如果打開,則接收焦點的元素是否在對話框內。如果滿足這兩個條件,則焦點將設置回對話框。這具有將焦點從對話底部循環回頂部的效果。結果是您無法跳出對話框,因此鍵盤用戶更難迷路。
如果您使用的是 JavaScript 庫,很可能它有一種委託 focus
的方法 事件的方式,你可以達到同樣的效果。如果您需要在沒有 JavaScript 庫的情況下支持 Internet Explorer 8 及更早版本,請使用 focusin
代替事件。
恢復焦點
對話框的焦點難題的最後一部分與關閉對話框時將焦點恢復到頁面的主要部分有關。這個想法很簡單:為了打開對話框,用戶可能激活了一個鏈接或一個按鈕。然後焦點轉移到對話框中,用戶在其中完成一些任務,然後關閉對話框。焦點應移回單擊以打開對話框的鏈接或按鈕,以便可以繼續導航頁面。這是 Web 應用程序中對話的一個經常被忽視的方面,但它卻有很大的不同。
與其他部分一樣,這需要很少的代碼即可工作。所有瀏覽器都支持 document.activeElement
,這是當前具有焦點的元素。您需要做的就是在顯示對話框之前查詢此值,然後在對話框關閉時將焦點設置回該元素。例如:
var lastFocus = document.activeElement,
dialog = document.getElementById("my-dialog");
dialog.className = "show";
dialog.focus();
這段代碼的重要部分是它跟踪最後一個焦點元素。這樣,當對話框關閉時,您需要做的就是將焦點重新設置回它:
lastFocus.focus()
總的來說,這增加了您可能已經為您的對話框添加的非常短的代碼行。
退出對話框
難題的最後一塊是讓用戶能夠快速簡便地退出對話框。最好的方法是讓 Esc 鍵關閉對話框。這是對話框在桌面應用程序中的工作方式,因此用戶非常熟悉。只需監聽 Esc 鍵被按下,然後退出對話框,如:
document.addEventListener("keydown", function(event) {
if (dialogOpen && event.keyCode == 27) {
// close the dialog
}
}, true);
keyCode
Esc 鍵的值為 27,因此您只需在 keydown
期間查找 事件。收到後,關閉對話框並將焦點重新設置回之前的焦點元素。
結論
正如我希望從這篇文章中顯而易見的那樣,創建一個屏幕閱讀器和只使用鍵盤的人都可以輕鬆訪問的對話框真的不需要很多額外的代碼。只需幾行代碼,您就可以讓您的用戶從難以置信的沮喪變成難以置信的快樂。有很多 Web 應用程序使用彈出對話框,但很少有人能正確處理所有這些部分。半途而廢比其他任何事情都更令人沮喪,所以我希望這篇文章能激發你讓你的對話盡可能容易訪問。
參考
- WAI-ARIA (W3C)
- 由 Peter-Paul Koch(Quirksmode)委派焦點和模糊事件