Is there a way to apply a parent’s tabindex to all of it’s children?
Example code:
<div id="app">
<div tabindex="2" class="parent-section">
Section 2
<a href="test.com" class="child-section bg-accent">test 2 a</a>
<a href="test.com" class="child-section bg-accent">test 2 b</a>
<a href="test.com" class="child-section bg-accent">test 2 c</a>
</div>
<div tabindex="1" class="parent-section flex-fill">
Section 1
<a href="test.com" class="child-section bg-neutral">test 1 a</a>
<a href="test.com" class="child-section bg-neutral">test 1 b</a>
<a href="test.com" class="child-section bg-neutral">test 1 c</a>
</div>
<div tabindex="3" class="parent-section">
Section 3
<a href="test.com" class="child-section bg-primary">test 3 a</a>
<a href="test.com" class="child-section bg-primary">test 3 b</a>
<a href="test.com" class="child-section bg-primary">test 3 c</a>
</div>
</div>
What I want is to focus first on section 1 div, and then each of it’s selectable child elements WIHOUT SETTING A PARTICULAR TABINDEX ON EACH CHILD. The. it would tab to section 2, and so on.
I made a StackBlitz to demonstrate. https://stackblitz.com/edit/typescript-ypkxx3?file=index.html. You see you will tab to the section 1 div, section 2 div, and section 3 div first; and then it tabs through all the anchor elements.
This is a really basic example. I have an app with much more complex sections. Basically, I want to be able to set the tabindex of the section, and have it trickle down to all of it’s focusable child elements. These sections are large and dynamic, so it wouldn’t work if I have to add a particular tabindex on every single child element.
My actual application is an angular project.
2
Answers
First off, non-interactive elements, such as a
<div>
should not receive keyboard focus. That will be confusing to both keyboard users, who might think they can hit ENTER on the element since it received focus, and it will be confusing for screen reader users because a role and label (accessible name) for the container won’t be announced.There is not a way to "inherit" the
tabindex
of a parent. You will have to set tabindex on all the children. You are allowed to have the same tabindex value for multiple elements. So your first container could havetabindex="1"
for all the links and they will be processed first. When multiple elements have the same tabindex value, the browser will process them in the DOM order.If you don’t want to set the tabindex, then you’ll need a keyboard event handler, perhaps on the
<body>
element, to override the browser’s tab behavior. You would have to programmatically move the focus to the next element and then drain the event so that the browser doesn’t try to move the focus.DOM order is really important in accessibility. So we should instead keep the items in order in the DOM and then change the visual order with CSS.
Note: 99% of the time "logical focus order" should go left to right (or RTL on RTL languages). I am assuming from the example given though that this is a general layout with 2 asides so it may be acceptable. Please take this into consideration though before you implement the following.
There is also a second point here, and that is that
tabindex
should hardly ever be greater than0
.If it is that means those items will be focusable first (so if you put this half way down a page the first Tab into the page would land at
tabindex="1"
and be confusing.Finally by changing the
tabindex
to0
it means we fixed your issue where the children elements are focused before the other parent elements astabindex="0"
doe not interfere with the natural focus order of the page.Using CSS to achieve your layout
We can use CSS flex
order
property to achieve your layout / request.What we do is put the DOM order back to Section 1, Section 2, Section 3 and then use the
order
property to adjust the order that things are focused.Example