Библиотека Tabbable предназначена для определения элементов на веб-странице, которые могут получать фокус с помощью клавиши Tab. Основное назначение — упрощение работы с доступностью (accessibility) и управлением фокусом в сложных интерфейсах, таких как модальные окна, панели навигации, кастомные компоненты.
Базовая функция библиотеки возвращает массив элементов, которые в
текущий момент считаются фокусируемыми. Эти элементы соответствуют
критериям видимости, интерактивности и отсутствию атрибута
tabindex="-1".
import tabbable from 'tabbable';
const container = document.querySelector('#modal');
const focusableElements = tabbable(container);
console.log(focusableElements);
tabbable(element, options) — основной метод.
element — корневой элемент, внутри которого
осуществляется поиск.
options — объект с дополнительными настройками:
includeContainer — если true, сам
контейнер тоже будет включён, если он фокусируемый.getShadowRoot — функция для работы с Shadow DOM,
возвращающая корень теневого дерева.includeDisabled — позволяет включать элементы с
атрибутом disabled.Наиболее распространённые причины:
display: none или
visibility: hidden).display: none.tabindex="-1", что исключает элемент из
обычного обхода клавишей Tab.getShadowRoot не настроена.Решение: проверить видимость элементов и
правильность атрибутов, при работе с Shadow DOM использовать
getShadowRoot.
const focusable = tabbable(container, {
getShadowRoot: el => el.shadowRoot
});
Custom элементы, такие как <my-button>, не всегда
автоматически распознаются как фокусируемые.
Решение: явно задавать tabindex="0" или
использовать свойства, позволяющие библиотеке распознавать кастомный
элемент как фокусируемый:
<my-button tabindex="0"></my-button>
Если элементы создаются после инициализации, вызов
tabbable до их добавления вернёт неполный список.
Решение: всегда вызывать функцию после вставки элементов в DOM или использовать MutationObserver для отслеживания изменений.
const observer = new MutationObserver(() => {
const updatedList = tabbable(container);
console.log(updatedList);
});
observer.observe(container, { childList: true, subtree: true });
disabled и aria-hiddenЭлементы с disabled или aria-hidden="true"
игнорируются. Иногда это создаёт неожиданные эффекты при модальных окнах
и диалогах.
Решение: использовать опцию
includeDisabled и корректно управлять
aria-hidden для скрытия контента.
const allFocusable = tabbable(container, { includeDisabled: true });
Иногда порядок обхода клавишей Tab не соответствует визуальному порядку. Причины:
tabindex (значения >0
нарушают естественный порядок).tabindex.Решение: придерживаться логики tabindex
= 0 для нормального обхода и избегать положительных чисел, если нужен
естественный порядок.
<input type="text" tabindex="0">
<button tabindex="0">Click</button>
tabbable(container)
в консоль для проверки всех найденных элементов.display, visibility,
opacity).getShadowRoot и
динамическое обновление списка элементов.tabindex и избегать
конфликтов с кастомными компонентами.Библиотека Tabbable позволяет создать стабильный и предсказуемый фокус для веб-интерфейсов, если учитывать особенности DOM, атрибутов и Shadow DOM. Внимательное управление параметрами и понимание причин исключений делает её инструментом высокого уровня для обеспечения доступности.