Positive tabindex and why it breaks the tab order
tabindex=1 pulls an element to the front of the tab order for the entire page. squirrel flags every positive value on every page.
What tabindex does
tabindex="0" puts an element into the tab order at its position in the document. tabindex="-1" takes it out of the tab order while leaving it focusable from script, which is what a modal’s container or a skip link’s target needs.
A positive value creates a second, earlier sequence. Every element with a positive tabindex is visited in ascending order before anything with 0 or a natural position. One tabindex="1" anywhere on a page therefore reorders the whole page, and adding a form field later puts it in a place nobody expects.
What squirrel checks
One rule, three check names, at severity warning. It reads every element carrying a tabindex, matching the attribute name case-insensitively so React’s tabIndex in server-rendered markup counts, and parses the value as an integer. Values of 0 and -1 are skipped, and a non-numeric value such as auto is ignored.
tabindex-very-highfails withN element(s) with very high tabindex valuesfor values above 100, carrying the issueVery high tabindex values indicate misuse. Items readdiv#hero (tabindex=9999), up to ten with a count of the rest.tabindex-positivewarns withN element(s) with positive tabindexfor values from 1 to 100, suggestingUse natural document order instead. Items read the same way, up to ten with a count of the rest.tabindexpasses withTabindex values are appropriate (0 or -1)when the page uses the attribute and no value is positive.tabindexreturns info withNo tabindex attributes found.
How to fix it
<div role="button" tabindex="0">Save</div>Delete the number and reorder the markup instead. Source order is what the tab sequence follows, and CSS can move things visually without touching it. Where visual and source order disagree badly, that is usually a layout problem worth fixing on its own.
Use tabindex="-1" for things focus should reach only from script: a dialog container, the target of a skip link, a region you move focus to after a route change.
| Rule ID | a11y/tabindex |
| Category | Accessibility |
| Scope | Per-page |
| Severity | warning |
| Weight | 5/10 |
Enable / disable
Disable this rule
[rules]
disable = ["a11y/tabindex"]Disable all Accessibility rules
[rules]
disable = ["a11y/*"]Enable only this rule
[rules]
enable = ["a11y/tabindex"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- a11y/focus-visible: focus-indicator styles, scanned for
outline: nonewithout a:focus-visiblefallback. - a11y/aria-hidden-focus: focusable elements inside a region hidden from assistive technology.
- a11y/skip-link: the bypass mechanism a positive
tabindexcan push out of first place. - a11y/duplicate-id-active: the other attribute problem specific to focusable elements.
Accessibility findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the Accessibility section of the report. Values above 100 are reported separately, since they almost always mean the attribute is being misused. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.