tabindex is the HTML attribute that decides whether an element can be focused with the Tab key and how it fits into the page’s focus order. When Lighthouse reports that elements have a value greater than zero, it’s warning that you’ve created a custom tab sequence that can jump around and confuse keyboard and screen reader users. Fixing it usually means removing positive values, relying on semantic controls like buttons and links, and ordering interactive elements logically in the DOM so visual layout does not fight keyboard navigation. Reserve 0 for truly custom widgets that must be reachable, and use -1 for things you only move focus to in code, such as modal containers or inline error messages; the trick is knowing when adding focus actually makes the experience worse.
Lighthouse error "No element has a tabindex value greater than 0"
Where to find it in the report
In a Lighthouse report, this issue appears under the Accessibility category as a failed audit named “No element has a tabindex value greater than 0.” If you’re running Lighthouse from Chrome DevTools, open the report, scroll to Accessibility, then expand the failed audits list. Selecting the audit shows a set of “offending” nodes so you can jump straight to the elements in the DOM.
You may see the same audit when Lighthouse is run through other tooling that uses Lighthouse under the hood (for example, site audit platforms or CI checks). The layout varies, but the clue is always the same: the audit name calls out tabindex values greater than 0, and the details panel lists the exact elements that triggered it.
What triggers the audit failure
This audit fails when Lighthouse detects any element with tabindex="1" or higher anywhere on the page. A positive tabindex forces that element into a custom keyboard focus order that runs before the normal, natural tab order. Once you start doing this, focus can move in a sequence that does not match the reading order, the visual layout, or user expectations.
Common ways this happens:
- A developer adds
tabindex="1",2,3, etc. to “fix” focus order after a CSS layout change. - A custom component (menu, carousel, tabs, dialog, tooltip trigger) ships with positive tabindex values.
- A third-party widget injects positive tabindex into the DOM at runtime.
Important nuance: Lighthouse is not saying “never use tabindex.” It is specifically flagging positive values. tabindex="0" (natural order) and tabindex="-1" (programmatic focus only) are typically the safer patterns and usually pass this audit.
What tabindex does to keyboard focus order
Default tab order without tabindex
By default, browsers build a keyboard focus order from elements that are natively focusable or made focusable by standard HTML features. This is the “natural” tab order most users expect. It generally follows the document order in the DOM.
Typical focusable elements without any tabindex include links with an href, form controls (like input, select, textarea, button), and elements with built-in focus behavior such as summary inside a details. Some elements become unfocusable when disabled, and some elements may be skipped if they are hidden (for example, display: none or visibility: hidden).
This default behavior is a major accessibility feature, not a limitation. When the DOM order matches the visual and reading order, keyboard navigation feels predictable. Screen readers also benefit because focus and reading order stay aligned.
How browsers sort focusable elements
When tabindex is present, it changes how an element enters the focus sequence:
tabindex="0"keeps the element in the normal tab order, based on DOM position. It’s commonly used for custom controls that aren’t naturally focusable (for example, a custom “button” built from adiv, although using a real<button>is usually better).tabindex="-1"removes the element from sequential keyboard tabbing, but still allows it to receive focus via code (likeelement.focus()). This is useful for focus management, such as moving focus into a modal, focusing an error message, or returning focus to a trigger after a UI change.tabindex="1"or higher creates a positive tabindex order. Browsers will focus elements with positive values first (sorted from 1 upward), and only then continue throughtabindex="0"and naturally focusable elements in DOM order.
That last rule is why positive tabindex is risky. Any time you add or remove interactive UI, the “carefully numbered” order can break. It can also fight responsive layouts, dynamic content, and component-based front ends where DOM order may change. The result is a page that technically works, but feels chaotic for keyboard users.
Why positive tabindex breaks accessibility and user expectations
Focus order vs visual order (CSS grid and flex)
Positive tabindex seems like an easy way to “make Tab go left to right,” but modern layouts make that a trap. With CSS Grid and Flexbox, you can visually rearrange items without changing their DOM order. Keyboard focus still follows the DOM unless you override it, and that’s usually the correct approach because DOM order is also the reading order for many assistive technologies.
When you add tabindex="1" and higher to force a visual sequence, you create two competing systems:
- The visual order can change across breakpoints (mobile vs desktop).
- The DOM order often reflects the content’s logical structure.
- The tabindex numbering becomes a fragile third layer that rarely stays correct as the UI evolves.
The result is a mismatch: a user sees one thing but focus jumps somewhere else. That mismatch is disorienting for keyboard users, and it can increase errors for screen reader users who rely on predictable navigation.
If you need a different focus sequence, the long-term fix is almost always to adjust the DOM order (or the component structure) so the natural tab order matches the intended user journey, instead of “programming around” layout with positive values. For the official guidance behind this Lighthouse audit, see the MDN tabindex reference.
Common user-impact scenarios
Positive tabindex tends to break real workflows in consistent, frustrating ways:
- Checkout and sign-up forms: Focus skips from “Email” to “Submit” and then back to “Password,” because a few fields were given
tabindex="1"and2months ago and the form later changed. - Header navigation: Keyboard users land in a hidden or collapsed menu item before reaching visible links, especially when responsive menus mount and unmount elements.
- Search and filters: A visually ordered filter sidebar (using flex or grid) tabs in a totally different sequence, making it hard to compare options.
- Modals and drawers: Focus moves behind the overlay because developers tried to “prioritize” modal buttons with positive tabindex instead of implementing a proper focus trap.
- Component libraries and third-party widgets: A single injected element with
tabindex="999"can hijack focus early in the tab cycle, making the page feel broken.
From an SEO standpoint in 2026, this matters more than just passing Lighthouse. Accessibility issues often correlate with usability friction, lower engagement, and higher abandonment, especially on mobile with external keyboards and assistive tech. Fixing positive tabindex is a practical way to improve real user experience, not just an audit score.
Finding elements with tabindex greater than 0
DevTools Elements panel and search
Start in Chrome DevTools because it lets you jump from the rendered page to the exact DOM node quickly.
- Open DevTools, then go to the Elements panel.
- Use the search box (Cmd+F on macOS, Ctrl+F on Windows) and search for
tabindex=". - Click through matches and look specifically for values like
tabindex="1",tabindex="2", and so on.
This approach is simple, but it can miss cases where a framework sets tabindex dynamically (for example, after opening a menu) or where the attribute is added without quotes. It also won’t help much if the widget is inside an iframe you have not inspected yet.
Console query to locate offenders
For a fast, reliable list, use a console query that finds every element with a positive tabindex:
[...document.querySelectorAll("[tabindex]")].filter(el => Number(el.getAttribute("tabindex")) > 0).map(el => ({
tabindex: el.getAttribute("tabindex"),
tag: el.tagName.toLowerCase(),
id: el.id || null,
class: el.className || null,
el
}));
This returns a table-like array you can expand. Click the el property to highlight the node in the Elements panel. If you suspect a third-party script, run the same snippet after interacting with the UI (open the modal, expand the menu, load more results) to catch elements added later.
Manual tabbing test for focus order
A quick human test often reveals problems faster than scanning code:
- Click the page background, then press Tab and watch where focus goes.
- Confirm the focus order matches the visual and reading order, especially in headers, forms, filters, and footers.
- Watch for “teleporting” focus, focus disappearing, or focus landing on elements that are offscreen or visually hidden.
Tip: if you can’t see focus clearly, that’s a separate accessibility problem. Many teams accidentally remove focus outlines in CSS, which makes tabindex issues harder to detect and harder for users to navigate.
Fixing tabindex greater than 0 without breaking UI
Removing tabindex and fixing DOM order instead
The safest fix is to delete positive values and make the natural tab order work for you.
Start by removing tabindex="1" (and any higher numbers). Then make sure interactive elements appear in a logical sequence in the DOM. If a card grid should tab left-to-right, top-to-bottom, the DOM needs to reflect that order. Use CSS for layout, not for reordering focus. In particular, avoid relying on flex or grid visual rearrangement (and the CSS order property) to communicate meaning, because keyboard focus will still follow the DOM.
If removing positive tabindex changes the user journey, treat that as a signal that the page structure needs attention. Common fixes include moving key controls earlier in the markup, grouping related form fields, and ensuring hidden content is truly removed from navigation until it is shown.
Using tabindex="0" and tabindex="-1" correctly
Use tabindex="0" only when you have a genuinely custom control that must be reachable by keyboard. In many cases, switching to a semantic element is better: a real <button> or <a href> usually removes the need for tabindex entirely.
Use tabindex="-1" for elements that should not be tabbable, but sometimes need focus moved to them programmatically. Examples include a modal container, a heading inside a dialog, a toast message, or an inline error summary.
One practical 2026 reality: AI-assisted code and component generators sometimes sprinkle in positive tabindex values to “fix” focus quickly. Build a habit of reviewing generated UI code for tabindex, especially in navigation, dialogs, and custom widgets.
Programmatic focus after UI changes (modals and drawers)
When a modal or drawer opens, focus should move inside it, stay inside while it’s open, and return to the trigger when it closes. A common pattern is:
- Give the dialog container (or a meaningful heading inside it)
tabindex="-1". - Call
.focus()after the dialog is rendered. - Trap Tab and Shift+Tab within the dialog.
- Restore focus to the opener on close.
For the expected keyboard behavior, follow the WAI-ARIA Authoring Practices dialog (modal) pattern.
Retesting after changes and preventing regressions
Rerun Lighthouse locally and in CI
After you remove positive tabindex values, rerun Lighthouse in the same conditions you use for other audits. Focus order bugs can be subtle, and you want confirmation that:
- The “No element has a tabindex value greater than 0” audit is now passing.
- Keyboard navigation still feels logical on real UI flows (login, checkout, navigation menus, modals).
For ongoing stability, add Lighthouse checks to continuous integration so tabindex regressions do not slip in with new UI work. A common approach is Lighthouse CI, which can run Lighthouse on every pull request and fail the build if accessibility scores or specific audits drop. This matters even more in 2026 workflows where teams ship faster with component libraries and AI-assisted code changes. A single copied snippet with tabindex="2" can quietly reintroduce the issue.
To prevent repeat failures, many teams also add a lint rule (for example, an accessibility lint rule that flags positive tabindex) so the mistake is caught before the browser ever runs it.
Handling third-party widgets that inject tabindex
Third-party chat widgets, booking tools, embedded reviews, and consent banners are frequent sources of positive tabindex. When the widget is the offender, you have a few practical options:
- Check vendor settings first. Some providers offer accessibility toggles, keyboard navigation modes, or updated embed code.
- Isolate the widget. If it can live in an iframe or a dedicated container that is not part of the primary journey, you reduce the chance it hijacks focus.
- Patch carefully as a last resort. You can remove or normalize injected
tabindexvalues after render, but this is brittle and can break vendor updates. If you do it, keep the change minimal (avoid rewriting focus behavior), and retest after every vendor release.
The goal is not just passing Lighthouse once. It’s keeping keyboard focus predictable as your site, scripts, and integrations evolve.