ARIA: button 角色
button 角色適用於使用者啟用時會觸發響應的可點選元素。新增 role="button" 會告訴螢幕閱讀器該元素是一個按鈕,但不會提供按鈕功能。請改用 <button> 或帶有 type="button" 的 <input>。
描述
按鈕角色將元素標識為輔助技術(如螢幕閱讀器)的按鈕。按鈕是一種小部件,用於執行操作,例如提交表單、開啟對話方塊、取消操作或執行命令(如插入新記錄或顯示資訊)。新增 role="button" 會告訴輔助技術該元素是一個按鈕,但不會提供按鈕功能。請改用 <button> 或帶有 type="button" 的 <input>。
這個 button 角色可以與 aria-pressed 屬性結合使用,以建立切換按鈕。
<div id="saveChanges" tabindex="0" role="button" aria-pressed="false">Save</div>
上述示例建立了一個可聚焦的按鈕,但需要 JavaScript 和 CSS 來包含按鈕的外觀和功能。這些功能在使用 <button> 和帶有 type="button" 的 <input> 元素時預設提供。
<button type="button" id="saveChanges">Save</button>
注意: 如果使用 role="button" 而不是語義化的 <button> 或 <input type="button"> 元素,您需要使該元素可聚焦,併為 click 和 keydown 事件定義事件處理程式。這包括處理 Enter 和 Space 鍵的按下,以便處理所有形式的使用者輸入。請參閱官方 WAI-ARIA 示例程式碼。
除了普通的按鈕小部件外,當使用非按鈕元素建立切換按鈕或選單按鈕時,也應包含 role="button"。
切換按鈕是一個兩態按鈕,可以是關閉(未按下)或開啟(已按下)。aria-pressed 屬性值 true 或 false 將按鈕標識為切換按鈕。
選單按鈕是一個控制選單的按鈕,並且具有設定為 menu 或 true 的 aria-haspopup 屬性。
所有後代都是展示性的
有些使用者介面元件在平臺輔助功能 API 中表示時,只能包含文字。輔助功能 API 沒有辦法表示 button 中包含的語義元素。為了解決這個限制,瀏覽器會自動將 presentation 角色應用於任何 button 元素的子孫元素,因為它是一個不支援語義子級的角色。
例如,考慮以下包含標題的 button 元素。
<div role="button"><h3>Title of my button</h3></div>
由於 button 的子孫元素是表示性的,以下程式碼是等效的
<div role="button"><h3 role="presentation">Title of my button</h3></div>
從輔助技術使用者的角度來看,標題不存在,因為前面的程式碼片段在輔助功能樹中等同於以下內容:
<div role="button">Title of my button</div>
關聯的 ARIA 角色、狀態和屬性
aria-pressed-
aria-pressed屬性將按鈕定義為切換按鈕。該值描述了按鈕的狀態。這些值包括按鈕當前未按下時的aria-pressed="false",表示按鈕當前已按下時的aria-pressed="true",以及如果按鈕被認為是部分按下時的aria-pressed="mixed"。如果省略該屬性或將其設定為預設值aria-pressed="undefined",則該元素不支援按下。 aria-expanded-
如果按鈕控制一組其他元素,
aria-expanded狀態指示受控組當前是展開還是摺疊。如果按鈕設定了aria-expanded="false",則該組當前未展開;如果按鈕設定了aria-expanded="true",則該組當前已展開;如果按鈕設定了aria-expanded="undefined"或省略了該屬性,則它不可展開。
基本按鈕
按鈕應始終具有可訪問的名稱。對於大多數按鈕,此名稱將與按鈕內部(開頭和結尾標籤之間)的文字相同。在某些情況下,例如由圖標表示的按鈕,可訪問的名稱可能由 aria-label 或 aria-labelledby 屬性提供。
切換按鈕
切換按鈕通常有兩種狀態:未按下和已按下。對於控制其他元素(例如其他切換按鈕或複選框)的切換按鈕,如果這些元素不都具有相同的值,則可以使用第三種混合狀態。元素是否為切換按鈕可以透過 button 角色(如果該元素還不是原生按鈕元素)以及 aria-pressed 屬性來指示。
- 如果未使用
aria-pressed,或將其設定為“undefined”狀態,則該按鈕不是切換按鈕。 - 如果使用
aria-pressed="false",則該按鈕是當前未按下的切換按鈕。 - 如果使用
aria-pressed="true",則該按鈕是當前已按下的切換按鈕。 - 如果使用
aria-pressed="mixed",則該按鈕被認為是部分按下的。
例如,音訊播放器上標記為“靜音”的靜音按鈕可以透過將 aria-pressed 狀態設定為 true 來指示聲音已靜音。切換按鈕的標籤不應在其狀態改變時改變。在我們的示例中,標籤仍然是“靜音”,螢幕閱讀器會根據 aria-pressed 的值讀取“靜音切換按鈕已按下”或“靜音切換按鈕未按下”。如果設計要求按鈕標籤從“靜音”更改為“取消靜音”,則切換按鈕將不適用,因此將省略 aria-pressed 屬性。
鍵盤互動
| 鍵 | Function |
|---|---|
| Enter | 啟用按鈕。 |
| 空格 | 啟用按鈕 |
按鈕啟用後,焦點設定取決於按鈕執行的操作型別。例如,如果單擊按鈕開啟對話方塊,焦點應移動到對話方塊。如果按鈕關閉對話方塊,焦點應返回到開啟對話方塊的按鈕,除非對話方塊上下文中執行的功能邏輯上導致不同的元素。如果按鈕改變當前上下文,例如靜音和取消靜音音訊檔案,則焦點通常會停留在按鈕上。
所需的 JavaScript 功能
所需的事件處理程式
按鈕可以透過滑鼠、觸控和鍵盤使用者操作。對於原生 HTML <button> 元素,當用戶點選滑鼠或在按鈕具有焦點時按下 Space 或 Enter 鍵時,按鈕的 onclick 事件會觸發。但如果使用其他標籤建立按鈕,即使使用 role="button",onclick 事件也只在滑鼠游標點選時觸發。因此,必須向元素新增單獨的按鍵事件處理程式,以便在按下 Space 或 Enter 鍵時觸發按鈕。
onclick-
處理使用滑鼠點選或觸控事件啟用按鈕時引發的事件。
onKeyDown-
處理使用鍵盤上的 Enter 或 Space 鍵啟用按鈕時引發的事件。(注意不是已棄用的 onKeyPress)
示例
基本按鈕示例
在此示例中,一個 span 元素被賦予了 button 角色。由於使用了 <span> 元素,因此需要 tabindex 屬性來使按鈕可聚焦併成為頁面 Tab 順序的一部分。提供的 CSS 樣式是為了使 <span> 元素看起來像一個按鈕,並在按鈕具有焦點時提供視覺提示。
handleBtnClick 和 handleBtnKeyDown 事件處理程式在透過滑鼠點選或 Space 或 Enter 鍵啟用時執行按鈕的操作。在這種情況下,操作是將新名稱新增到名稱列表中。
透過在文字框中新增名稱來嘗試該示例。按鈕將使該名稱新增到列表中。
HTML
<h1>ARIA Button Example</h1>
<ul id="nameList"></ul>
<label for="newName">Enter your Name: </label>
<input type="text" id="newName" />
<span role="button" tabindex="0">Add Name</span>
CSS
[role="button"] {
padding: 2px;
background-color: navy;
color: white;
cursor: default;
}
[role="button"]:hover,
[role="button"]:focus,
[role="button"]:active {
background-color: white;
color: navy;
}
ul {
list-style: none;
}
JavaScript
function handleCommand(event) {
// Handles both mouse clicks and keyboard
// activate with Enter or Space
// Key presses other than Enter and Space should not trigger a command
if (
event instanceof KeyboardEvent &&
event.key !== "Enter" &&
event.key !== " "
) {
return;
}
// Get the new name value from the input element
const newNameInput = document.getElementById("newName");
const name = newNameInput.value;
newNameInput.value = ""; // clear the text field
newNameInput.focus(); // give the text field focus to enable entering and additional name.
// Don't add blank entries to the list.
if (name.length > 0) {
const listItem = document.createElement("li");
listItem.appendChild(document.createTextNode(name));
// Add the new name to the list.
const list = document.getElementById("nameList");
list.appendChild(listItem);
}
}
const btn = document.querySelector("span[role='button']");
btn.addEventListener("click", handleCommand);
btn.addEventListener("keydown", handleCommand);
切換按鈕示例
在此程式碼片段中,一個 <span> 元素透過使用 button 角色和 aria-pressed 屬性轉換為切換按鈕。當按鈕被啟用時,aria-pressed 值會切換狀態;從 true 變為 false,然後再變回來。
HTML
<button type="button">Mute Audio</button>
<span role="button" tabindex="0" aria-pressed="false"> Mute Audio </span>
<audio
id="audio"
src="https://soundbible.com/mp3/Tyrannosaurus%20Rex%20Roar-SoundBible.com-807702404.mp3">
Your browser does not support the `audio` element.
</audio>
CSS
button,
[role="button"] {
padding: 3px;
border: 2px solid transparent;
}
button:active,
button:focus,
[role="button"][aria-pressed="true"] {
border: 2px solid black;
}
JavaScript
function handleBtnClick(event) {
toggleButton(event.target);
}
function handleBtnKeyDown(event) {
// Check to see if space or enter were pressed
// "Spacebar" for IE11 support
if (event.key === " " || event.key === "Enter" || event.key === "Spacebar") {
// Prevent the default action to stop scrolling when space is pressed
event.preventDefault();
toggleButton(event.target);
}
}
function toggleButton(element) {
const audio = document.getElementById("audio");
// Check to see if the button is pressed
const pressed = element.getAttribute("aria-pressed") === "true";
// Change aria-pressed to the opposite state
element.setAttribute("aria-pressed", !pressed);
// Toggle the play state of the audio file
if (pressed) {
audio.pause();
} else {
audio.play();
}
}
const button = document.querySelector("button");
const spanButton = document.querySelector("span[role='button']");
button.addEventListener("click", handleBtnClick);
button.addEventListener("keydown", handleBtnKeyDown);
spanButton.addEventListener("click", handleBtnClick);
spanButton.addEventListener("keydown", handleBtnKeyDown);
結果
可訪問性考慮
按鈕是互動式控制元件,因此可聚焦。如果將 button 角色新增到本身不可聚焦的元素(例如 <span>、<div> 或 <p>),則必須使用 tabindex 屬性使按鈕可聚焦。
警告: 用按鈕角色標記連結時要小心。按鈕預期透過 Space 或 Enter 鍵觸發,而連結預期透過 Enter 鍵觸發。換句話說,當連結被用作按鈕時,僅新增 role="button" 是不夠的。還需要新增一個監聽 Space 鍵的按鍵事件處理程式,以便與原生按鈕保持一致。
當使用 button 角色時,螢幕閱讀器會將元素宣佈為按鈕,通常會說“點選”後跟按鈕的可訪問名稱。可訪問名稱是元素的內容,或者是 aria-label 的值,或由 aria-labelledby 屬性引用的元素,或者如果包含的話,是描述。
最佳實踐
如果一個連結執行按鈕的操作,給該元素 role="button" 有助於輔助技術使用者理解該元素的功能。然而,一個更好的解決方案是調整視覺設計,使其與功能和 ARIA 角色匹配。在可能的情況下,建議使用原生的 HTML 按鈕(<button>、<input type="button">、<input type="submit">、<input type="reset"> 和 <input type="image">),而不是 button 角色,因為原生 HTML 按鈕受到所有使用者代理和輔助技術的支援,並預設提供鍵盤和焦點要求,無需額外定製。
規範
| 規範 |
|---|
| 無障礙富網際網路應用程式 (WAI-ARIA) # button |
| 未知規範 |