如何使 div 及其所有后代无法聚焦

How to make a div and all its descendants unfocusable

我试图让 div 及其所有后代都无法聚焦。我在根 div 上使用了 tabIndex -1。但这使焦点转移到它的第一个可聚焦 child。 (默认行为)是否有解决此问题的方法?

示例代码

const SomeFunctionComponent = () => {
  // ... some logic ...

  const someTrustedHtml = `<p>Hello <a href="whosebug.com">World!</a></p>`;
  const content = React.createElement("div", {
    className: "some class name",
    dangerouslySetInnerHTML: {
      __html: someTrustedHtml;
    },
    tabIndex: -1, /* "tabindex": -1 does not work */
    // None of these options helped either
    // "data-is-focusable": false,
    // "aria-hidden": true,
    // disabled: true,
    // role: "presentation"
  });

  // ... more logic ...
  
  return (
    <div>
      {content}
      <button onClick={() => console.log("hello world")}></button>
      {/* some tab focusable elements */}
    </div>
  );
}

预期行为: 当 SomeFunctionComponent 获得焦点时,焦点将移动到按钮

实际行为: 焦点转到 dangerouslySetInnerHtml

中的 link

tabindex 不可继承。您必须在每个原生可聚焦的元素上设置它。

有趣的是,规范说将它设置为 -1 确实 不会 导致元素不可聚焦,但我一直使用它并且它适用于所有浏览器。

Note that the tabindex attribute cannot be used to make an element non-focusable. The only way a page author can do that is by disabling the element, or making it inert.

没有简单的解决方案。正如另一个答案所说,您必须遍历 div.

内的所有可聚焦对象

事实上,与其在 div 内的所有可聚焦元素上设置 tabindex=-1,不如通过 display:none 或隐藏属性完全隐藏 div 更好,或将表单字段的禁用属性用作第二选择。 隐藏的元素不可聚焦。

设置 disabled 属性对于让用户直观地看到 he/she 当前无法使用该字段以及告知屏幕 reader 用户这一事实很重要。 所以,这是更可取的。将 disabled 属性设置为 true 自动意味着该字段不再可聚焦。

提醒一下,设置 tabindex=-1 不会使元素完全无法聚焦。 它不允许用户再使用 tab 键或其他常规方式对其进行聚焦,但它仍然可以通过编程方式进行聚焦(使用 focus() 方法)。 请注意,完全有可能通过用户脚本绕过直接无法聚焦。

正如其他人所说,tabindex 不可继承。但是,焦点陷阱是否可以帮助您实现类似的目标,也许方式略有不同?焦点陷阱就像它们听起来的那样 - 它们将焦点限制在一个元素及其后代中。与您尝试做的听起来有点相反,但它可能会产生一些帮助。 https://github.com/focus-trap/focus-trap