( Operable / WCAG 2.1.1 )
Focus skipped an interactive element
What is this issue?
An element that looks and behaves like a normal interactive control, visible on screen, styled as clickable, present in the DOM, does not receive keyboard focus when a user Tabs to where it sits in the reading order. The most common concrete cause is tabindex="-1" applied to an element that was meant to stay in the natural Tab sequence, since a negative tabindex removes an element from Tab navigation while still allowing it to be focused programmatically via JavaScript.
A second common cause is a CSS mismatch: an ancestor element with visibility: hidden or display: none that a later, more specific rule only partially reverses on the child, leaving the child rendered visually while still excluded from the accessibility tree and the tab order. Either way, the element that’s skipped is otherwise a completely ordinary, fully built interactive control: the defect is entirely in what’s stopping focus from reaching it.
Why does this matter?
An element a keyboard user can see but can’t reach is arguably more confusing than one that’s hidden entirely, because there’s a visible, working-looking control sitting right there with no way to use it. A sighted keyboard user watches the focus indicator jump past a button they can clearly see and has no way to tell whether that’s a bug, an intentional design choice, or a sign the button doesn’t actually work.
For anything gating a task (a “Submit” button skipped in a checkout flow, an “Accept” button skipped on a required consent screen), this isn’t a minor inconvenience, it blocks the task outright. The user can see exactly what they need to do and still can’t do it with the input method they’re using.
Who is affected?
- Keyboard users: cannot Tab to the element at all, even though it’s visibly present and would otherwise work exactly like any other control on the page.
- Motor impairments: anyone relying on a switch device or keyboard-only navigation because precise mouse control isn’t available to them hits the same dead end as any other keyboard user, with no fallback.
- Screen reader users: many screen reader users navigate primarily via Tab and keyboard shortcuts rather than a mouse pointer, so an element skipped from the tab order is functionally unreachable for them too, on top of whatever a screen reader’s separate element-list navigation might or might not surface.
What users experience
Tomás uses a keyboard exclusively because a hand tremor makes precise mouse clicks unreliable. On a hotel booking site, the “Confirm booking” button visually sits at the bottom of a form, styled and positioned exactly like every other button on the page. He tabs through the guest details fields expecting to land on it next, but focus jumps straight to the footer’s newsletter signup instead: a developer had set tabindex="-1" on the confirm button months earlier to work around an unrelated animation bug, and never removed it. Tomás can see the button, cannot reach it with Tab, and has no way to complete the booking.
How do I fix it?
Remove the tabindex="-1" (or whatever attribute or CSS is excluding the element) from any control meant to stay in the normal tab sequence. This works because native interactive elements are focusable by default; the fix is almost always subtraction, undoing whatever override is suppressing behavior the browser would otherwise provide automatically.
If the cause is CSS rather than an attribute, trace the element’s computed style back through its ancestors (browser DevTools’ Computed panel shows the winning rule and where it came from) to find the visibility or display rule responsible, then scope that rule so it doesn’t apply to elements that need to stay interactive. After either fix, Tab through the affected area again and confirm the element now receives focus at the point in the sequence a sighted user would expect.
Code Examples
<!-- tabindex="-1" left over from an unrelated bug fix -->
<button tabindex="-1" class="confirm-booking">Confirm booking</button><button class="confirm-booking">Confirm booking</button>Removing the attribute restores the button’s default, built-in focusability with no other code required. Native elements need no extra markup to be keyboard-reachable, only the absence of something actively suppressing it.
Common Mistakes
Mistake: “tabindex=‘-1’ just means ‘not the first thing focused,’ so it’s a minor tweak.” tabindex="-1" removes an element from the Tab sequence entirely, not just from the front of it: a user pressing Tab will never land on the element no matter how many times they press the key. It only remains reachable via JavaScript calling .focus() directly, which most page interactions never do.
Mistake: “If it renders and looks clickable, it must be keyboard-reachable too.” Visual rendering and keyboard reachability are controlled by entirely separate mechanisms: one by CSS layout and paint, the other by the DOM’s focus system and any tabindex/visibility overrides on it. An element can look completely normal and still be fully excluded from the Tab sequence, which is exactly why this defect survives casual visual review.
Mistake: “We only need to test the elements a screen reader announces, not raw Tab order.” A screen reader user tabbing through a page hits this exact same skip a sighted keyboard user does. Reading a screen reader’s separate elements list doesn’t substitute for confirming the actual Tab sequence reaches every interactive control in the order a sighted user would expect.
How RedFlag Detects This
Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s focus-skipped rule as part of every scan, restricted to the WCAG 2.0/2.1/2.2 A and AA rule set (extension/content.js’s AXE_SCAN_OPTIONS). The rule inspects elements that are natively or previously interactive and checks for a concrete, detectable exclusion condition: a tabindex="-1" on an element type that’s normally in the tab order by default, or a computed-style mismatch between visible rendering and accessibility-tree exclusion.
False negative: a custom element built from a non-interactive tag (<div>, <span>) that was simply never given tabindex in the first place has no prior focusable state for this rule to detect a regression from; that case is covered separately, and manually, by Interactive element is not reachable by keyboard. False positive: an element deliberately set to tabindex="-1" as part of a legitimate roving-tabindex or programmatic-focus-on-open pattern can be flagged if axe-core can’t confirm the surrounding code moves focus to it another way. Manual step: Tab through the flagged area and confirm whether the element is genuinely meant to be reachable by Tab, or intentionally focus-managed some other way.
Manual Testing
- Open the page in Chrome or Firefox using only the keyboard.
- Identify every visible interactive element (buttons, links, form fields) in the area under test.
- Tab through the page from the top and confirm focus lands on each one, in an order that matches the visual layout.
- For any element focus skips over, inspect it in DevTools’ Accessibility pane and check its
tabindexand computedvisibility/displayvalues. - Fix the attribute or CSS rule responsible, then Tab through the same area again to confirm the element now receives focus.
Related WCAG Success Criteria
2.1.1 Keyboard: All functionality must be operable through a keyboard interface. A skipped interactive element fails this directly whenever activating it is the only way to complete a task, since the keyboard-only path to it no longer exists.
2.4.3 Focus Order: Components must receive focus in an order that preserves meaning and operability. A skip doesn’t just misorder the sequence, it removes a stop from it entirely, which is a more severe version of the same underlying requirement that a merely-wrong tab order also violates.
Related Issues
Interactive element is not reachable by keyboard covers the same “Tab skips over it” symptom for custom-built elements that were never made focusable at all, which this page’s automated detector can’t reliably catch. The two pages are companions covering the detectable and undetectable halves of the same problem.
Focus is trapped inside a component is the opposite direction of keyboard failure: focus getting stuck inside a component instead of never reaching an element in the first place.
Page has no skip navigation link and Skip link target is missing or not focusable cover related keyboard-navigation gaps at the page level, where the missing reachability is a whole content region rather than a single control.
References
Frequently asked questions
Is this the same issue as redflag-keyboard-trap?
They cover the same symptom, an element Tab skips over, but different causes and different detectability. This rule catches native or previously-focusable elements with a concrete technical cause, like a stray tabindex="-1" or a CSS visibility mismatch, which axe-core can detect. Interactive element is not reachable by keyboard covers custom-built div or span elements that were never wired for the keyboard at all, which requires manual review to catch reliably.
Can tabindex="-1" ever be correct on an interactive element?
Yes, when it is set deliberately to remove an element from the natural Tab sequence while keeping it programmatically focusable, for example a modal heading that JavaScript moves focus to on open, but that a user should not land on again by pressing Tab repeatedly. The problem this rule documents is tabindex="-1" applied by accident to something meant to be a normal, Tab-reachable control.
Does display:none cause this, or a different failure?
display:none removes an element from the accessibility tree entirely, so a screen reader never announces it at all; that is a more complete removal than this rule covers. This rule is specifically about elements that remain visible and interactive-looking on screen but are unreachable by Tab, which is a narrower and often more confusing mismatch for sighted keyboard users.
Why would a visible element ever get skipped by CSS rather than an attribute?
Overlapping elements, negative CSS positioning intended to visually hide a duplicate label, or an ancestor with visibility:hidden that a later rule only partially overrides on the child can all leave an element rendered and visible while excluded from the accessibility tree or the tab order, without a single obvious attribute to blame.