Библиотека Tabbable в JavaScript используется для определения элементов на странице, которые могут получать фокус при навигации с помощью клавиши Tab. Она особенно полезна при разработке доступных интерфейсов для пользователей со специальными потребностями, включая использование скринридеров. Основная цель Tabbable — выявление всех интерактивных элементов, корректное управление фокусом и поддержка логической последовательности навигации.
Tabbable возвращает массив элементов, которые считаются доступными для табуляции. Ключевые критерии:
display: none или visibility: hidden).disabled).tabindex.tabbableОсновной метод библиотеки — функция
tabbable(root, options), где:
root — DOM-элемент, внутри которого производится
поиск tabbable-элементов. Если передать document.body,
поиск осуществляется по всей странице.
options — объект с дополнительными настройками:
includeContainer — включает переданный элемент в
результирующий массив, если он сам по себе tabbable.getShadowRoot — функция, возвращающая shadow DOM для
обхода вложенных элементов.displayCheck — задаёт способ проверки видимости:
'full' (полная проверка CSS), 'non-zero-area'
(проверка размеров).Пример использования:
import { tabbable } from 'tabbable';
const elements = tabbable(document.body, { includeContainer: true });
console.log(elements); // Список всех интерактивных элементов
tabindexЭлемент с tabindex получает особое значение:
tabindex="0" — элемент включается в обычную
последовательность табуляции.tabindex="-1" — элемент исключён из табуляции, но
доступен для программного фокуса через
element.focus().tabindex>0 — элемент имеет приоритет в
последовательности табуляции (устаревший подход, рекомендуется
избегать).Tabbable учитывает эти значения при формировании порядка фокусировки, что критично для доступности и взаимодействия со скринридерами.
Формы и кнопки
Элементы <button>, <input>,
<select>, <textarea> автоматически
считаются tabbable, если они не отключены и видимы. Для
<input type="hidden"> исключение — такие элементы не
учитываются.
Ссылки
Элементы <a> с атрибутом href
включаются в последовательность табуляции. Если href
отсутствует, элемент становится фокусируемым только при явном
tabindex.
Контейнеры и роли ARIA
Элементы с ролями ARIA, такими как role="button" или
role="link", могут быть сделаны tabbable с помощью
tabindex="0". Tabbable корректно
определяет такие элементы, что обеспечивает совместимость со
скринридерами.
Для интерфейсов с модальными окнами, аккордеонами или вкладками важно обновлять список tabbable-элементов при изменении DOM. Пример для модального окна:
const modal = document.querySelector('.modal');
const focusableElements = tabbable(modal);
focusableElements[0].focus(); // Устанавливаем фокус на первый элемент при открытии
При закрытии модального окна фокус можно возвращать на элемент, инициировавший открытие, чтобы сохранить последовательность навигации.
Для обеспечения доступности часто используется концепция focus trap — ограничение табуляции внутри модального окна или панели. Tabbable предоставляет основу для реализации:
function trapFocus(container) {
const elements = tabbable(container);
const first = elements[0];
const last = elements[elements.length - 1];
container.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
}
Такой подход предотвращает потерю фокуса за пределами модального окна и обеспечивает корректное взаимодействие со скринридерами.
Shadow DOM добавляет сложность при поиске tabbable-элементов.
Tabbable поддерживает обход вложенных shadow root через
опцию getShadowRoot:
const elements = tabbable(document.body, {
getShadowRoot: (node) => node.shadowRoot
});
Это позволяет учитывать интерактивные элементы внутри веб-компонентов и сохранять логичную последовательность табуляции.
aria-hidden="true" или CSS-свойства
display: none) исключаются.Библиотека допускает создание собственных фильтров для специфичных элементов:
const customElements = tabbable(document.body).filter(el => el.tagName === 'BUTTON' || el.hasAttribute('data-focus'));
Это позволяет ограничивать навигацию клавишами только на определённые интерактивные элементы без изменения структуры DOM.
Tabbable — ключевой инструмент для построения доступных интерфейсов. Его использование обеспечивает правильное управление фокусом, совместимость с ARIA и скринридерами, а также позволяет реализовать современные паттерны взаимодействия, включая модальные окна, аккордеоны и кастомные компоненты.