默认情况下,互动元素(包括表单控件、链接和按钮)可聚焦且可使用 Tab 键。可 Tab 键切换的元素是文档的依序焦点导航顺序的一部分。 其他元素处于非活动状态,这意味着它们不具有互动性。借助 HTML 属性,您可以使互动元素处于惰性状态,并使惰性元素具有互动性。
默认情况下,导航焦点顺序与视觉顺序(即源代码顺序)相同。有些 HTML 属性可以改变此顺序,有些 CSS 属性可以改变内容的视觉顺序。使用 HTML 更改 Tab 键顺序或使用 CSS 更改视觉呈现顺序可能会损害用户体验。
请勿使用 CSS 和 HTML 更改感知到的和实际的 Tab 键顺序。如以下两个示例所示,与视觉预期顺序不同的 Tab 键顺序会让用户感到困惑,并且不利于用户体验。
在以下示例中,tabindex 属性的值导致了 Tab 键顺序混乱:
在此示例中,CSS 在内容的 Tab 键顺序和视觉顺序之间造成了差异:
flex-flow: row-reverse; 声明颠倒了视觉顺序。此外,CSS order 属性应用于第六个单词“This”,这在视觉上移动了该单词。Tab 键顺序是代码的顺序,不再与视觉顺序一致。
这会导致键盘用户无法正常使用。
某些 CSS 功能(包括 flexbox、网格、定位、转换和多列)可以改变内容的视觉顺序。使用键盘按 Tab 键浏览内容,以测试内容:按 Shift + Tab 键可向后浏览内容。使用 CSS 指示哪个元素具有焦点。请勿使用 CSS 重新排列可聚焦元素的顺序。
请务必在所有视口尺寸上保持逻辑 Tab 键顺序。
使惰性元素可交互
contenteditable 和 tabindex 属性是全局属性,可以添加到任何元素中,从而使这些元素在处理过程中可聚焦。可聚焦元素也可以通过鼠标或指针、通过设置 autofocus 属性或通过脚本(例如使用 element.focus())进行聚焦。
tabindex 属性
tabindex 全局属性(在属性中介绍)使原本无法获得焦点的元素能够获得焦点,通常使用 Tab 键,因此得名。
tabindex 属性的值为整数。负值会使元素可聚焦,但不可通过 Tab 键访问。tabindex 值为 0 会使元素可聚焦和可按 Tab 键,从而将应用该元素的元素添加到源代码顺序中的依序焦点导航顺序中。值为 1 或更大值会使元素可聚焦和可按 Tab 键,但会将其添加到优先的 Tab 键序列中,应避免使用。
在此页面上,分享按钮 <share-action> 是一个自定义元素。tabindex="0" 会将此元素添加到键盘默认 Tab 键顺序中:
<share-action authors="@front-end.social/@estellevw" data-action="click"
data-category="web.dev" data-icon="share" data-label="share, mastodon"
role="button" tabindex="0">
<svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
<use href="#shareIcon" />
</svg>
<span>Share</span>
</share-action>
此外,本地导航具有一个 tabindex 值为负数的自定义元素:
<web-navigation-drawer type="standard" tabindex="-1">
值为负数的 tabindex 属性会使元素可聚焦,但不可通过 Tab 键聚焦。该元素可以获得焦点(例如使用 HTMLElement.focus()),但它不属于依序焦点导航顺序。对于不可通过 Tab 键聚焦但可聚焦的元素,惯例是使用 tabindex="-1"。如果您向互动元素添加 tabindex="-1",该元素将不再可通过 Tab 键访问。
element.focus() 方法可用于将焦点设置到可聚焦元素。浏览器会将获得焦点的元素滚动到视图中。因此,请避免使用 element.focus({preventScroll:true}),因为聚焦于不可见元素会带来糟糕的用户体验。
如果您想查询文档以找出哪个元素具有焦点,请使用只读 Document.activeElement 属性。
tabindex 为 1 或更大的元素会包含在单独的 Tab 键顺序中。如以下 Codepen 所示,按 Tab 键时,焦点会先从一个单独的序列开始,按照从最低值到最高值的顺序移动,然后再按照源代码顺序移动到常规序列(未设置 tabindex 或设置为 tabindex="0")中的元素:
tabindex 值为正数时,元素会进入优先焦点序列,这可能会导致焦点顺序混乱。避免使用 tabindex 修改 DOM 顺序。更改后的 Tab 键顺序可能会导致糟糕的用户体验,并且难以维护。
contenteditable 属性
contenteditable 是一个全局属性。在任何元素上设置 contenteditable="true" 都会使其可修改、可聚焦,并成为 Tab 键顺序的一部分。焦点行为与设置 tabindex="0" 类似,但不完全相同。
嵌套的 contenteditable 元素可聚焦,但无法通过 Tab 键访问。如需使嵌套的 contenteditable 元素可聚焦,请添加 tabindex="0",这会将该元素添加到依序焦点导航顺序中。
为互动元素提供 autofocus
虽然布尔值 autofocus 是一个全局属性,可以设置在任何元素上,但它不会使惰性元素具有互动性。网页加载后,只要具有 autofocus 属性的第一个可聚焦元素已显示且未嵌套在 <dialog> 中,该元素就会获得焦点。
自动将焦点设置在内容上可能会让用户感到困惑。在表单控件上设置 autofocus 时,该表单控件会在网页加载时滚动到视图中。您的用户(包括屏幕阅读器用户和视口较小的用户)可能会错过表单的说明,甚至错过表单控件的标签。此外,autofocus 属性不会改变文档的顺序焦点导航顺序。序列中位于自动对焦元素之前的元素会被跳过。由于这些原因,您应避免使用 autofocus 属性。
“不使用 autofocus”建议的例外情况是在 <dialog> 元素中添加 autofocus 属性。打开对话框时,浏览器会自动聚焦于 <dialog> 内的第一个可聚焦互动元素,这意味着无需向元素添加 autofocus。如果您想确保对话框打开时,对话框内的特定互动元素获得焦点,请向该元素添加 autofocus 属性。
<dialog open>
<form method="dialog">
<button type="submit" autofocus>close</button>
</form>
</dialog>
在关闭 <button> 上设置的 autofocus 属性使其能够在对话框打开时获得焦点。作为对话框中的第一个元素,它在任何情况下都会获得焦点。默认情况下,打开对话框时,对话框中第一个可聚焦的元素会获得焦点,除非对话框中的其他元素设置了 autofocus 属性。
使互动元素处于惰性状态
还有一些 HTML 属性可以从 Tab 键序列中移除互动元素。向可聚焦元素添加负 tabindex、向支持的表单控件添加 disabled 属性,以及向容器添加全局 inert 属性,都会使元素无法通过 Tab 键聚焦。这三个属性完全独立,不可互换。
tabindex 值为负
具有负值的 tabindex 属性会使元素可聚焦,但不可通过 Tab 键访问。虽然无需向默认可聚焦的元素(包括链接、按钮、表单控件和 contenteditable 元素)添加 tabindex="0",但添加值为负数的 tabindex 会从依序焦点导航顺序中移除通常可按 Tab 键聚焦的元素。
负 tabindex 值会阻止键盘用户聚焦于互动元素,但不会停用该元素。指针用户仍然可以聚焦于该元素。如需停用某个元素,请使用 disabled 属性。
已停用
布尔值 disabled 属性会使应用了该属性的表单控件及其后代(如有)无法聚焦。已停用的表单控件无法获得焦点,不会收到点击事件,也不会在表单提交时一并提交。
disabled 不是全局属性。它适用于 <button>、<input>、<optgroup>、<option>、<select>、<textarea>、与表单关联的自定义元素和 <fieldset>。在 <optgroup> 或 <fieldset> 上设置时,所有子表单控件都会被停用,但 <fieldset> 的第一个 <legend> 的内容除外。
支持 disabled 的元素也可以使用 :disabled 和 :enabled 伪类进行定位。使用 disabled 属性停用的元素通常会使用用户代理样式表设置为浅灰色,即使设置了 accent-color 也是如此。
作为一个布尔值属性,该属性的存在会停用原本处于启用状态的元素;您无法将其设置为 false。如需重新启用已停用的元素,必须移除该属性,通常使用 Element.removeAttribute('disabled')。
HTMLInputElement.disabled 属性可让您检查输入是否已停用。由于 disabled 不是全局属性,因此它不会从 HTMLElement 继承,但每个支持元素接口(例如 HTMLSelectElement、HTMLTextareaElement)都具有相同的只读属性。
disabled 属性不适用于通过 tabindex 或 contenteditable 设为可聚焦的通常 inert 元素,也不适用于 <form> 元素。如需停用这些元素,可以使用全局 inert 属性。
inert 属性
将 inert 全局布尔值属性添加到某个元素后,该元素和所有嵌套内容都会被停用,这意味着它们无法被点击或通过 Tab 键访问。它们也会从无障碍功能树中移除。虽然 inert 可应用于任何元素,但通常用于内容部分,例如屏幕外内容或其他隐藏的内容。
将 disabled 应用于表单控件时,浏览器会提供默认样式,并且可以使用 :disabled 伪类设置样式。inert 属性不提供视觉指示器,也没有匹配的伪类(尽管 [inert] 属性选择器匹配)。
在可见内容上使用 inert,而不使用指示惰性的样式,可能会导致用户体验不佳。由于屏幕阅读器用户无法访问惰性内容,因此当视力正常的屏幕阅读器用户看到屏幕上存在无障碍工具无法访问的内容时,可能会感到困惑。使用 CSS 让惰性状态非常明显。
确保焦点永远不会移至不可见的内容。任何在屏幕外呈现且在获得焦点时不会自动进入视图的内容都应设为惰性。如果内容处于隐藏状态,但在获得焦点时会显示(例如跳至内容链接),则无需将其设为惰性。
检查掌握情况
测试您对焦点的了解程度。
如果某个元素无法聚焦,则会被描述为什么?
如果元素具有 disabled 属性,以下哪项说法是正确的?