Focus

默认情况下,交互式元素(包括表单控件链接和按钮)是可聚焦和可使用 Tab 键选取的。可使用 Tab 键选取的元素是文档的顺序焦点导航顺序的一部分。其他元素是惰性的,这意味着它们不具有交互性。借助 HTML 属性,可以使交互式元素变为惰性,并使惰性元素变为交互式。

默认情况下,导航焦点顺序与视觉顺序相同,视觉顺序与源代码顺序相同。有些 HTML 属性可以更改此顺序,有些 CSS 属性可以更改内容的视觉顺序。使用 HTML 更改 Tab 键选取顺序或使用 CSS 更改视觉呈现顺序可能会损害用户体验。

请勿使用 CSS 和 HTML 更改感知到的和实际的 Tab 键选取顺序。以下两个示例表明,Tab 键选取顺序与视觉预期顺序不同的情况会让用户感到困惑,并且会给用户带来糟糕的体验。

在此示例中,tabindex 属性的值使 Tab 键选取顺序变得混乱

在此示例中,CSS 在 Tab 键选取顺序和内容的视觉顺序之间造成了差异

flex-flow: row-reverse; 声明反转了视觉顺序。此外,CSS order 属性应用于第六个单词“This”,这在视觉上移动了该单词。“Tab 键选取”序列是代码的顺序,该顺序不再与视觉顺序匹配,从而为键盘用户造成了脱节感。

使惰性元素变为交互式

contenteditabletabindex 属性是全局属性,可以添加到任何元素,从而使这些元素在此过程中变为可聚焦的。可聚焦元素也可以通过鼠标或指针聚焦,方法是设置 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 属性。

tabindex1 或更大的元素包含在单独的 Tab 键选取序列中。正如您将在 Codepen 中注意到的那样,Tab 键选取在单独的序列中开始,顺序为从最低值到最高值,然后再遍历源代码顺序中的常规序列(未设置 tabindextabindex="0")中的元素

具有正值的 tabindex 将元素放入优先级更高的焦点序列中,这可能会导致焦点顺序混乱。避免使用 tabindex 修改 DOM 顺序。更改后的 Tab 键选取顺序不仅会给用户带来糟糕的体验,而且还难以供开发者管理和维护。

contenteditable 属性

前面讨论过 contenteditable 属性。在任何元素上设置 contenteditable="true" 都会使其变为可编辑、可聚焦和 Tab 键选取顺序的一部分。焦点行为类似于设置 tabindex="0",但不完全相同。嵌套的 contenteditable 元素是可聚焦的,但不可使用 Tab 键选取。要使嵌套的 contenteditable 元素可使用 Tab 键选取,请添加 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 继承,但每个支持的元素接口(如 HTMLSelectElementHTMLTextareaElement)都具有相同的只读属性。

disabled 属性不适用于通常 inert 的元素,这些元素通过 tabindexcontenteditable 变为可聚焦的。它也不适用于 <form> 元素本身。要停用这些元素,可以使用全局 inert 属性。

inert 属性

当全局布尔值 inert 属性添加到元素时,该元素和所有嵌套内容都将变为已停用(既不可点击也不可使用 Tab 键选取),并从无障碍功能树中移除。虽然 inert 可以应用于任何元素,但它通常用于内容部分,例如屏幕外内容或其他隐藏内容。

当将 disabled 应用于表单控件时,浏览器会提供默认样式,并且可以使用 :disabled 伪类设置样式。inert 属性不提供视觉指示器,并且没有匹配的伪类(尽管 [inert] 属性选择器匹配)。

在可见内容上使用 inert 而没有指示惰性的样式可能会导致糟糕的用户体验。由于惰性内容对屏幕阅读器用户不可用,因此当有视觉障碍的屏幕阅读器用户在屏幕上看到对无障碍功能工具不可用的内容时,可能会导致困惑。通过 CSS 使惰性非常明显。

确保焦点永远不会移动到不可见的内容。任何在屏幕外呈现且在聚焦时不会自动进入视图的内容都应设置为惰性。如果内容是隐藏的,但在聚焦时会进入视图,例如此页面上的跳到内容链接,则无需将其设置为惰性。

检查您的理解情况

检查您的理解情况

测试您对焦点的了解程度。

如果某个元素无法聚焦,则将其描述为什么?

空。
再试一次。
惰性。
正确!
隐藏。
再试一次。

如果元素具有 disabled 属性,则什么将为真?

它将变为不可聚焦的。
正确!
它将不会显示。
再试一次。
如果它是表单元素,则不会提交。
正确!