ARIA: button 角色

button 角色適用於使用者啟用時會觸發響應的可點選元素。新增 role="button" 會告訴螢幕閱讀器該元素是一個按鈕,但不會提供按鈕功能。請改用 <button> 或帶有 type="button"<input>

描述

按鈕角色將元素標識為輔助技術(如螢幕閱讀器)的按鈕。按鈕是一種小部件,用於執行操作,例如提交表單、開啟對話方塊、取消操作或執行命令(如插入新記錄或顯示資訊)。新增 role="button" 會告訴輔助技術該元素是一個按鈕,但不會提供按鈕功能。請改用 <button> 或帶有 type="button"<input>

這個 button 角色可以與 aria-pressed 屬性結合使用,以建立切換按鈕

html
<div id="saveChanges" tabindex="0" role="button" aria-pressed="false">Save</div>

上述示例建立了一個可聚焦的按鈕,但需要 JavaScript 和 CSS 來包含按鈕的外觀和功能。這些功能在使用 <button> 和帶有 type="button"<input> 元素時預設提供。

html
<button type="button" id="saveChanges">Save</button>

注意: 如果使用 role="button" 而不是語義化的 <button><input type="button"> 元素,您需要使該元素可聚焦,併為 clickkeydown 事件定義事件處理程式。這包括處理 EnterSpace 鍵的按下,以便處理所有形式的使用者輸入。請參閱官方 WAI-ARIA 示例程式碼

除了普通的按鈕小部件外,當使用非按鈕元素建立切換按鈕或選單按鈕時,也應包含 role="button"

切換按鈕是一個兩態按鈕,可以是關閉(未按下)或開啟(已按下)。aria-pressed 屬性值 truefalse 將按鈕標識為切換按鈕。

選單按鈕是一個控制選單的按鈕,並且具有設定為 menutruearia-haspopup 屬性。

所有後代都是展示性的

有些使用者介面元件在平臺輔助功能 API 中表示時,只能包含文字。輔助功能 API 沒有辦法表示 button 中包含的語義元素。為了解決這個限制,瀏覽器會自動將 presentation 角色應用於任何 button 元素的子孫元素,因為它是一個不支援語義子級的角色。

例如,考慮以下包含標題的 button 元素。

html
<div role="button"><h3>Title of my button</h3></div>

由於 button 的子孫元素是表示性的,以下程式碼是等效的

html
<div role="button"><h3 role="presentation">Title of my button</h3></div>

從輔助技術使用者的角度來看,標題不存在,因為前面的程式碼片段在輔助功能樹中等同於以下內容:

html
<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-labelaria-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> 元素,當用戶點選滑鼠或在按鈕具有焦點時按下 SpaceEnter 鍵時,按鈕的 onclick 事件會觸發。但如果使用其他標籤建立按鈕,即使使用 role="button"onclick 事件也只在滑鼠游標點選時觸發。因此,必須向元素新增單獨的按鍵事件處理程式,以便在按下 SpaceEnter 鍵時觸發按鈕。

onclick

處理使用滑鼠點選或觸控事件啟用按鈕時引發的事件。

onKeyDown

處理使用鍵盤上的 Enter 或 Space 鍵啟用按鈕時引發的事件。(注意不是已棄用的 onKeyPress

示例

基本按鈕示例

在此示例中,一個 span 元素被賦予了 button 角色。由於使用了 <span> 元素,因此需要 tabindex 屬性來使按鈕可聚焦併成為頁面 Tab 順序的一部分。提供的 CSS 樣式是為了使 <span> 元素看起來像一個按鈕,並在按鈕具有焦點時提供視覺提示。

handleBtnClickhandleBtnKeyDown 事件處理程式在透過滑鼠點選或 SpaceEnter 鍵啟用時執行按鈕的操作。在這種情況下,操作是將新名稱新增到名稱列表中。

透過在文字框中新增名稱來嘗試該示例。按鈕將使該名稱新增到列表中。

HTML

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

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

js
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

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

css
button,
[role="button"] {
  padding: 3px;
  border: 2px solid transparent;
}

button:active,
button:focus,
[role="button"][aria-pressed="true"] {
  border: 2px solid black;
}

JavaScript

js
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 屬性使按鈕可聚焦。

警告: 用按鈕角色標記連結時要小心。按鈕預期透過 SpaceEnter 鍵觸發,而連結預期透過 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
未知規範

另見