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

Posted

技术标签:

【中文标题】如何使 div 及其所有后代无法聚焦【英文标题】:How to make a div and all its descendants unfocusable 【发布时间】:2022-01-23 02:44:43 【问题描述】:

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

示例代码

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

  const someTrustedhtml = `<p>Hello <a href="***.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 获得焦点时,焦点会移动到按钮上

实际行为: 焦点转到危险的SetInnerHtml中的链接

【问题讨论】:

【参考方案1】:

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

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

请注意,tabindex 属性不能用于使元素不可聚焦。页面作者可以做到这一点的唯一方法是禁用该元素,或使其变为惰性。

【讨论】:

【参考方案2】:

没有简单的解决方案。正如另一个答案所说,您必须遍历 div 内的所有可聚焦对象。

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

设置 disabled 属性对于让用户直观地看到他/她当前无法使用该字段以及告诉屏幕阅读器用户这一事实非常重要。 所以,更可取。将 disabled 属性自动设置为 true 意味着该字段不再具有焦点。

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于如何使 div 及其所有后代无法聚焦的主要内容,如果未能解决你的问题,请参考以下文章

如何使 div 之外的所有内容变暗?

jQuery:后代选择器仅适用于一个“隐藏”的 div

Jquery如何选取元素及其所有子元素?

课时71.后代选择器(掌握)

jQuery遍历-后代

洛谷P3388 模板割点