Tabindex on elements that are interactive only under certain conditions

tabindex on anchor tag
tabindex not working in firefox
tabindex javascript
tabindex -1 focus
tabindex= -1 means
html focusable
html tabstop
keyboard navigation html

In our web application we use multiple "responsive" HTML tables — they can be scrolled horizontally if their content gets too wide (CSS rules: width:100%; overflow-x: auto;). This allows to show all the necessary information in the table without breaking the layout and making the whole page horizontally scrollable.

In our case, this is relevant only for small screens (on resized browser windows or if the user increases the font-size by over 200%) as our tables aren't that big (note that the application is internal and will only be used on laptop/desktop screens).

Unfortunately, making content horizontally scrollable with overflow-x isn't accessible for keyboard users — the only way to scroll through the content would be with the mouse; using the arrow keys only works if the whole page is scrollable or if the element has focus.

So, in order to make our tables controllable with the keyboard, I was thinking about adding tabindex="0" to them and thus allowing to use the arrow keys. This seems to work fine if the table is scrollable, but also means that a non-interactive element (the table on a big screen) can receive focus, which might result in confusion in keyboard users.

Here is a little example (made with Bootstrap to spare writing some CSS). Resize the browser window to test it:

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<h1>Some heading</h1>
<a href="#">First link (for tabbing purposes)</a>

<table class="table table-responsive" tabindex="0">
    <thead>
        <tr>
           <th scole="col">Column 1</th>
           <th scole="col">Column 2</th>
           <th scole="col">Column 3</th>
           <th scole="col">Column 4</th>
           <th scole="col">Column 5</th>
           <th scole="col">Column 6</th>
           <th scole="col">Column 7</th>
        </tr>
    </thead>

    <tbody>
        <tr>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
           <td>Lorem ipsum</td>
        </tr>
    </tbody>
</table>

<a href="#">Second link (for tabbing purposes)</a>

In general, I would agree with @quentinc that putting the focus on a non-interactive element is not ideal (I wouldn't go so far as to say it's a "bad idea"), but it does give the keyboard user a way to scroll. I use the keyboard for most of my interactions and I don't have any other way to scroll. I don't know what roulette is and as far as I know, the browser doesn't have any dedicated keys for horizontal scrolling, other than left/right arrows, which you already mentioned scrolls the page and not the table, unless the table can receive focus, thus the reason for this question.

On firefox, the table will already receive focus because anytime a container has a scrollbar, firefox allows the focus to move to that object, specifically to allow scrolling. So you are already getting the behavior you want in firefox. You're just trying to enable that same behavior for chrome, safari, and internet explorer.

If you put tabindex="0" on the table, you can also add a visually hidden <caption> to the table to tell the screen reader that focus was moved to the table to allow keyboard users to scroll horizontally. Something like this:

<table class="table table-responsive" tabindex="0">
  <caption class="sr-only">table receives focus so keyboard users can scroll it</caption>

(The "sr-only" class is from bootstrap too. See What is sr-only in Bootstrap 3?. You don't have to use bootstrap but can create your own class that is similar.)

However, one drawback of allowing the table to receive focus is that NVDA will announce the entire contents of the table when it receives focus. This is kind of annoying. Here's what NVDA says:

table  with 2 rows and 7 columns 
table receives focus so keyboard users can scroll it
Column 1
Column 2
Column 3
Column 4
Column 5
Column 6
Column 7
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum

You might argue that that's a problem with NVDA, and maybe it is. When an object receives focus, it's accessible name should be announced. In the case of the table, the accessible name is sort of the contents of the table, although one could also argue the accessible name should be the <caption> and that's all that should be read. You can file a bug for NVDA if you think the behavior is incorrect. If the table didn't have a <caption>, then I could see the entire contents being read so I think you have a case that NVDA is wrong.

I tried working around it by putting a title, aria-label, and aria-labelledby on the table (not all at the same time) but the entire table was always read (in addition to the title or label).

But I also agree again with @quentinc that horizontal scrolling should be avoided if possible. On internet explorer, you don't even see the horizontal scrollbar until you actually start scrolling (with the keyboard) so you might not know there's more information to the right unless you can see some of the text clipped on the edge of the table. (Note, the scrollbar appears if you hover over the table with the mouse, but we're talking about keyboard users.)

Tough situation. Without the focus, a keyboard user can't scroll the table. With the focus, a screen reader might hear all kinds of extra stuff. In the former, there isn't any kind of workaround. In the latter, while it's noisy to hear all that read, the screen reader user can hit ctrl to immediately silence the screen reader (and hopefully they silence it after hearing the <caption> read).

Elements should not have tabindex greater than zero Axe Rules , Only links and form elements can receive the tab focus under normal conditions. to the tab flow, but under some exceptional circumstances — such as some kinds of complex interactive JavaScript widgets — it can make sense to add items​  Applying tabindex="0" to an element makes it keyboard focusable, whether it is an interactive HTML element or not. This can be useful for building custom form controls or application components. but can also be a potential accessibility hazard if these elements don’t have correct WAI-ARIA attributes to make their usage clear to people with screen readers.

Using tabindex | Web Fundamentals, Managing focus at the page level; Managing focus in components; Modals and keyboard traps; Feedback tabindex="0" : Inserts an element into the natural tab order. If you do use tabindex , restrict it to custom interactive controls like Here's a scenario where tabindex is not only useful, but necessary. The tabindex attribute can adjust the natural focus order of interactive elements like buttons and form inputs. For instance, tabindex="1" lets you make an element the first element focusable within a page, irrespective of where it appears in the source.

Instead of tabindex attribute on the table, You can provide two buttons for scroll up and scroll down at the end of the table or at other place where a user can access it easily. I think it would be better for all users including user with a pointing device etc.

Technique: Focus order and tabindex, Interactive elements should, under most circumstances, be focusable in the order that they appear in the source code. This helps people who are using the  Control focus with tabindex. Native HTML elements such as <button> or <input> have keyboard accessibility built in for free. If you're building custom interactive components, however, use the tabindex attribute to ensure that they're keyboard accessible. Whenever possible, use a native HTML element rather than building your own custom version. <button>, for example, is very easy to style and already has full keyboard support.

tabindex, The tabindex global attribute indicates that its element can be when you have off-screen content that appears on a specific event. something intended to be interactive focusable by keyboard input. The newsletter is offered in English only at the moment. Content is available under these licenses. The tabindex attribute can be applied to almost any element, whether it is by default focusable or not. The value of the attribute must be a valid integer and can either be negative, positive, or exactly zero. Negative tabindex values. A negative tabindex, for example -1, will omit the element from the focus order entirely. A user navigating the page using a keyboard will not be able to access the element at all.

Keyboard-navigable JavaScript widgets, With the tabindex global attribute, authors can make other elements focusable, too. In exceptional circumstances, authors may want to redefine the order. Native HTML elements that are interactive, like <a> , <input> and <select> DOM focus events are considered informational only: generated by the  That is, tabindex="4" is focused before tabindex="5" and tabindex="0", but after tabindex="3". If multiple elements share the same positive tabindex value, their order relative to each other follows their position in the document source. The maximum value for tabindex is 32767. If not specified, it takes the default value 0.

H4: Creating a logical tab order through links, form controls, and , See Understanding Techniques for WCAG Success Criteria for important information about the When the interactive elements are navigated using the tab key, the elements are given focus in increasing order of the value of their tabindex attribute. Resources are for information purposes only, no endorsement implied. The tabindex attribute of 1+ explicitly defines the navigation order for focusable elements (typically links and form controls) within a page. It can also be used to define whether elements should be focusable or not. In theory, tabindex should only be used in cases where: The default tab order is not ideal, AND

Comments
  • what about using JS to add/remove the tabindex attribute based on the screen size?
  • @VelimirTchatchevsky, I thought about this, but the tables have different initial width - I can't be sure at which exact breakpoint they are going to get scrollable.
  • you should be able to calculate that on page load, comparing the table width and the viewport