TabIndex On A Non-Interactive Element

ID

javascript.jsx_non_interactive_element_tabindex

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

accessibility, jsx, reliability

Description

Reports a JSX element put into the tab order although its tag carries a structural role and no interactive role replaces it.

Rationale

A non-negative tabIndex adds a tab stop, and a tab stop is a promise: the user who lands there expects something to operate. On an element whose role says it is content — a list item, a heading, a paragraph, an image — there is nothing to operate, so every keyboard user pays an extra Tab press for a stop that does nothing, and a screen reader announces content in a position where a control was expected. Long lists make this expensive fast.

<li tabIndex={0}>Details</li>                    // FLAW - a tab stop that does nothing
<img src="x.png" alt="Chart" tabIndex="0" />     // FLAW - same
<li role="listitem" tabIndex={0}>Details</li>    // FLAW - the role confirms it is content

<li role="option" tabIndex={0}>Details</li>      // OK - the role makes it a control
<li tabIndex={-1}>Details</li>                   // OK - focusable from script only
<div tabIndex={0}>Details</div>                  // OK - div has no role to contradict
<li role={kind} tabIndex={0}>Details</li>        // OK - computed role, semantics unknown

Two shapes are commonly meant instead, and neither is reported: tabIndex={-1}, which keeps the element focusable from script without adding a tab stop, and an interactive role on the same element, which makes the tab stop honest. div and span are deliberately not judged — they carry no implicit role for a tab stop to contradict — and neither are the table row and cell tags, which in a grid take tabIndex exactly as intended.

Remediation

Remove the tabIndex, or lower it to -1 if script needs to move focus there. If the element really is a control, give it the interactive role that says so along with the key handling to match.

© 2026 Xygeni. All rights reserved