如何防止按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-label
或 aria-labelledby
为其指定一个可访问的名称
- 给它一个 active/inactive 状态,它控制选项卡是在它内部导航,还是导航到下一个组件
- 听 Enter 和 Escape 来切换此状态
- 收听 Tab 和
focusin
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.
在页面上按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-label
或aria-labelledby
为其指定一个可访问的名称
- 给它一个 active/inactive 状态,它控制选项卡是在它内部导航,还是导航到下一个组件
- 听 Enter 和 Escape 来切换此状态
- 收听 Tab 和
focusin
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.