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
未知规范

另见