如何防止按Tab键进入交互元素?

how to prevent entering interactive elements by press tab?

在页面上按Tab键的同时, 当在一个交互元素(用户定义)上进行 Tab 时,它会自动进入它,并且 Tab 在交互元素的内部子元素上导航

如何防止这种情况?

我希望我们可以使用enter/esc来获取in/out这个交互元素,而不是直接点击它进入它。

更多详情: 我试着弄清楚我的问题:假设我的页面有两个元素,比如一个按钮和一个 excel 呈现视图,我可以使用 tab 来关注它们,但是 excel 的视图是一个交互式的元素,这意味着当我在 excel 的视图上切换时,下面的选项卡将在 excel 的单元格中移动我希望我只能在按钮和 [=20= 的视图之间切换],仅当我在 excel 的视图上使用回车键,然后让它在 excel 的单元格之间切换时,希望我可以使用 ESC 键从视图中删除 excel

不是答案,但我建议您也查看 tabindex HTML attribute, and possibly accesskey。我想发表评论,但我没有足够的声誉。

如果用户组件允许通过 table 末尾的制表符退出,则不会失败 WCAG 2.1.2 No Keyboard Trap

话虽这么说,但正如您已经意识到的那样,这并不是很好的用户体验。

如果您对该组件没有任何控制权,您可以尝试以下操作:

  • 通过tabindex="0"
  • 使组件的包装器可聚焦
  • 通过 aria-labelaria-labelledby
  • 为其指定一个可访问的名称
  • 给它一个 active/inactive 状态,它控制选项卡是在它内部导航,还是导航到下一个组件
  • EnterEscape 来切换此状态
  • 收听 Tabfocusin event,以避免在未激活时在内部导航(您可以跳过收听 Tab,因为结果会成为另一个焦点)
  • 不要忘记向用户(包括屏幕 reader 用户)解释如何导航

c = document.getElementById('component');
next = document.getElementById('next-tabstop');

c.addEventListener('keydown', e => {
  switch (e.code) {
    case "Tab":
      // Tab to the next component if not active
      if (c.dataset.active !== "true") {
        next.focus();
        e.preventDefault();
      }
      break;

    case "Escape":
      // Exit tab of the table
      c.dataset.active="false";
      c.focus();
      break;

    case "Enter":
      // Tab into the table
      c.dataset.active="true";
      c.querySelector("[tabindex='0']").focus();
      break;
  }
});

// Avoid backwards navigation directly onto the last focusable descendend
c.addEventListener('focusin', e => {
  if (c.dataset.active !== "true") {
    c.focus();
  }
});
table {
  border-collapse: collapse;
}

td,
th {
  padding: .5em;
  border: 1px solid grey;
}

:focus {
  outline: 2px solid orange;
}
<p><button>A humble button</button></p>

<h2 id="component-title">Table</h2>
<p id="component-desc">Press <kbd>Enter</kbd> to navigate into the table, <kbd>Escape</kbd> to exit the table</p>

<div tabindex="0" aria-labelledby="component-title" aria-describedby="component-desc" id="component" data-active="false">
  <table>
    <thead>
      <tr>
        <th tabindex="0"></th>
        <th tabindex="0">A</th>
        <th tabindex="0">B</th>
        <th tabindex="0">C</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th tabindex="0">1</th>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
      </tr>
      <tr>
        <th tabindex="0">2</th>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
      </tr>
      <tr>
        <th tabindex="0">3</th>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
        <td tabindex="0"></td>
      </tr>
    </tbody>
  </table>
</div>

<p><button id="next-tabstop">Let’s move on</button></p>

要有一个可访问的页面,table 组件也需要可访问,并且有更多的准则需要遵循。

人们希望通过箭头键在网格中导航,而且 Home 和 End 应该与某些修饰符一起使用。例如,参见 ARIA Practice of Keyboard Navigation for Data Grids

如果这些单元格中再次有小部件,它会变得复杂,因为那时 table 本身的键盘控制变得困难。可以参考ARIA Grid Widget Role.