While pressing tab on the page, when tab on one interactive element(user defined), it automatically enter into it, and the tab navigating on the internal subelemnet of the interactive element
how to prevent this?
I hope we can use enter/esc to get in/out this interactive element, not directly get into it while tab on it.
moer details: I try to clear my question: Suppose my page have two elements like one button and one excel render view, I can use tab to focus on both of them, however, the view of excel is an interactive element, which means when I tab on the view of excel, the following tab will move in the cells of the excel I hope I can only tab between the button and the view of the excel, only if I use the enter key on the view of the excel, then let it tab between cells of the excel, and hopefully I can use ESC key to leave out from the view the excel
If the user component allows exiting by means of tab at the end of the table, you are not failing WCAG 2.1.2 No Keyboard Trap.
That being said, and as you already have realised, this is not a great user experience.
If you don’t have any control on that component, this is something you could try:
tabindex="0"
aria-label
or aria-labelledby
focusin
event, to avoid navigation inside when it’s not active (you might skip listening on Tab, as the result would be another focusin)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>
To have an accessible page, the table component needs to be accessible, as well, and there are more guidelines to follow.
One would expect to navigate grids by means of arrow keys, and also Home and End should work with certain modifiers. See, for example, ARIA Practice of Keyboard Navigation for Data Grids
If inside these cells there are widgets again, it’s going to get complicated, because then keyboard control of the table itself becomes difficult. You can refer to the ARIA Grid Widget Role.