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