Registry / web-framework / tabbable

tabbable

JSON →
library6.4.0jsnpmunverified

tabbable is a JavaScript utility library designed to accurately identify and return an array of all keyboard-tabbable DOM nodes within a specified container element. It systematically determines tabbability based on standard HTML semantics (e.g., `<button>`, `<input>`, `<a>` with `href`), explicit `tabindex` attributes, and various visibility and accessibility rules. The library is actively maintained, currently at version `6.4.0`, and receives regular minor and patch updates to enhance browser compatibility, support new web standards like the `inert` attribute, and address issues in virtual DOM environments like JSDOM. Its key differentiators include a zero-dependency footprint, small bundle size, high accuracy in diverse scenarios, and optimized performance. It supports a broad range of modern desktop browsers (Chrome, Edge, Firefox, Safari, Opera), but crucially, it dropped support for Internet Explorer browsers starting with v6.0.0. The library also provides granular control over how visibility checks are performed via the `displayCheck` option, accommodating various application needs.

npm install tabbable
INSTALL
IMPORT
SIG · TABBABLE
T
tabbable
web-frameworkjavascriptv6.4.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

tabbable
import { tabbable } from 'tabbable';
const { tabbable } = require('tabbable');
ESM is the recommended import style as shown in documentation, though CommonJS is also supported.
focusable
import { focusable } from 'tabbable';
const focusable = require('tabbable').focusable;
Used to get all focusable elements, which includes tabbable elements and those with `tabindex="-1"`.
getTabIndex
import { getTabIndex } from 'tabbable';
import { getTabIndex } from 'tabbable/dist/getTabIndex';
Introduced in v6.2.0, provides the computed tab index for an element, aligning with tabbable's internal logic.

Demonstrates how to find both tabbable and focusable elements within a given DOM node using the `tabbable` and `focusable` functions, and how to retrieve their `tabIndex`.

import { tabbable, focusable, getTabIndex } from 'tabbable'; // Helper to create a DOM structure for testing in a browser or JSDOM environment function createTestDOM(htmlString) { const container = document.createElement('div'); container.innerHTML = htmlString; // Append to body to ensure elements are considered 'attached' for visibility checks document.body.appendChild(container); return container; } const testHtml = ` <div id="root-container"> <button id="btn1">Click Me</button> <input type="text" placeholder="Enter text" /> <a href="#" id="link1">A link</a> <span tabindex="0" id="span1">Custom tabbable</span> <div tabindex="-1" id="div1">Focusable but not tabbable</div> <button disabled id="btn2">Disabled Button</button> <a href="#" style="display: none;" id="link2">Hidden Link</a> <p>Some text</p> <textarea id="textarea1"></textarea> </div> `; const containerElement = createTestDOM(testHtml); console.log('--- Tabbable elements ---'); const tabbableElements = tabbable(containerElement); tabbableElements.forEach(el => { console.log(`Tabbable: ${el.outerHTML}, TabIndex: ${getTabIndex(el)}`); }); console.log('\n--- Focusable elements (including non-tabbable) ---'); const focusableElements = focusable(containerElement); focusableElements.forEach(el => { console.log(`Focusable: ${el.outerHTML}, TabIndex: ${getTabIndex(el)}`); }); // Clean up the added DOM element document.body.removeChild(containerElement);
Debug
Known issues
breakingSupport for Internet Explorer (all versions) has been officially dropped. The library no longer guarantees functionality or provides fixes for IE environments.
fix
Migrate your application to modern browsers. If IE11 support is critical, you must use `tabbable` v5.x or earlier.
affects: >=6.0.0
gotchaThe `inert` HTML attribute, which prevents focus and interaction, is not consistently supported across all major browsers (notably Firefox and Safari as of February 2023). While `tabbable` includes checks for `inert`, its effectiveness depends on browser-level support.
fix
For full compatibility and consistent behavior, consider polyfilling the `inert` attribute or implementing custom focus management for browsers that do not natively support it. Always test in target environments.
affects: >=6.1.0
gotchaWhen running in JSDOM environments, versions prior to v26 may exhibit issues with CSS selectors related to the `inert` attribute, leading to incorrect identification of tabbable nodes. `tabbable` v6.4.0 re-enabled a CSS selector fast path for `inert`.
fix
Upgrade JSDOM to version 26 or newer to ensure accurate `inert` attribute handling. If upgrading is not feasible, be aware that manual checks for inertness or adjustments to `displayCheck` might be necessary.
affects: >=6.1.1 <6.4.0
gotchaThe default `displayCheck='full'` option may inaccurately determine all nodes are hidden if the container element is not attached to the document. In such cases, `tabbable` may revert to `displayCheck='none'` behavior.
fix
Ensure the container element is attached to the document (e.g., `document.body.appendChild(container)`) when using `displayCheck='full'` or `displayCheck='non-zero-area'`. Alternatively, set `displayCheck='none'` explicitly if working with detached DOM nodes.
affects: >=5.3.2
gotchaVery old browser environments might require a polyfill for the `CSS.escape` API, especially if you have radio buttons with special characters in their `name` attributes. Without it, `tabbable` might not work correctly with such elements.
fix
If supporting legacy browsers, install and include a `CSS.escape` polyfill (e.g., `npm install css.escape`).
affects: all
Errors
Common errors & fixes
focus-trap must have at least one tabbable node in it
This error often originates from `focus-trap` (which uses `tabbable`) when the underlying `tabbable` library cannot find any tabbable elements in a JSDOM environment or due to incorrect `inert` attribute handling.
fix
Ensure your JSDOM setup is current (v26+). Verify that elements within the trapped container are not inadvertently hidden or marked `inert` in a way not supported by your browser/JSDOM version. Consider adding `tabindex="0"` to explicitly make an element tabbable if it should be.
TypeError: Cannot read properties of undefined (reading 'getRootNode')
This crash occurs when a DOM node being evaluated by `tabbable` is detached from the document, causing `isHidden()` to fail during a call to `getRootNode()`.
fix
Ensure that any DOM nodes passed to `tabbable` (or its internal functions) are attached to the document. This issue was largely fixed in `v6.1.0` to handle detached nodes more gracefully, but may still manifest in specific edge cases or older versions.
Upgrade
Version history
6.4.0latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
3 hits · last 30 days
node
2
Resources