Библиотека Tabbable предназначена для определения элементов на странице, которые могут получать фокус при навигации с помощью клавиши Tab. Она не управляет самим фокусом, а предоставляет точный список элементов, на которые возможно переключение, что особенно важно при реализации модальных окон, кастомных виджетов и сложных интерфейсов.
Метод tabbable(container) возвращает массив элементов
внутри указанного контейнера, которые могут быть сфокусированы. Эти
элементы учитывают следующие условия:
offsetParent не равен null,
visibility и display корректны).disabled не установлен).<input>, <button>,
<a href> или элемент с атрибутом
tabindex ≥ 0).Это позволяет точно определить порядок навигации клавишей Tab, избегая элементов, которые на практике недоступны пользователю.
Порядок табуляции формируется на основе атрибутов
tabindex:
tabindex получают
приоритет.tabindex или с tabindex="0"
следуют естественному DOM-порядку.tabindex="-1" исключаются из навигации.Использование Tabbable упрощает вычисление правильного порядка при динамическом добавлении или удалении элементов, например, при открытии модального окна или разворачивании аккордеона.
Пример:
import { tabbable } from 'tabbable';
const modal = document.querySelector('.modal');
const focusableElements = tabbable(modal);
focusableElements[0].focus(); // автоматический фокус на первый доступный элемент
При работе с длинными страницами часто требуется, чтобы элемент,
получивший фокус, был виден пользователю. Для этого используется метод
element.scrollIntoView(). Библиотека
Tabbable напрямую не управляет прокруткой, но комбинация с этим методом
позволяет реализовать плавное перемещение:
const firstFocusable = tabbable(modal)[0];
firstFocusable.focus();
firstFocusable.scrollIntoView({ beh * avior: 'smooth', block: 'center' });
Ключевые моменты:
beh * avior: 'smooth' обеспечивает плавную анимацию
прокрутки.block: 'center' гарантирует, что элемент окажется по
центру видимой области.Если содержимое страницы динамически изменяется (например, открытие вкладки или модального окна), необходимо пересчитывать tabbable-элементы, чтобы корректно установить фокус. Пример стратегии:
tabbable(modal).const triggerButton = document.querySelector('.open-modal');
triggerButton.addEventListener('click', () => {
const modal = document.querySelector('.modal');
modal.style.display = 'block';
const focusableElements = tabbable(modal);
focusableElements[0].focus();
});
Использование Tabbable гарантирует, что даже при
сложной структуре DOM первый элемент для фокуса будет выбран корректно,
без ошибок с tabindex и скрытыми элементами.
Tabbable особенно полезна в следующих сценариях:
Библиотека позволяет интегрировать фокус с дополнительными функциями — проверкой видимости, управлением скроллом и циклом фокусировки, что делает интерфейс доступным и предсказуемым для пользователей.
Для полного контроля над навигацией часто комбинируют Tabbable с обработкой событий клавиш:
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
const focusableElements = tabbable(modal);
const first = focusableElements[0];
const last = focusableElements[focusableElements.length - 1];
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
Такой подход обеспечивает циклическую навигацию, предотвращает уход фокуса за пределы модального окна и повышает доступность интерфейса.
scrollIntoView для элементов, находящихся
вне видимой области.tabindex и избегать отрицательных
значений для интерактивных элементов.Эти подходы позволяют строить интерфейсы с предсказуемым и корректным поведением фокуса, улучшая доступность и пользовательский опыт.