Библиотека Tabbable предназначена для определения элементов веб-страницы, которые могут быть фокусируемыми с помощью клавиши Tab. Основная задача библиотеки — корректная идентификация таких элементов с учётом стандартов HTML, CSS и доступности (accessibility). Она обеспечивает точное вычисление фокусируемых элементов, включая сложные случаи с вложенными или скрытыми элементами.
Ключевые моменты:
disabled, hidden,
aria-hidden, tabindex).tabindex. Элементы с tabindex="0" участвуют в
естественном порядке, отрицательные значения исключают элемент из
порядка табуляции, положительные — задают явный приоритет.<a> считаются фокусируемыми только при
наличии атрибута href. Кнопки <button> и
поля ввода <input> фокусируются по умолчанию.Установка через npm:
npm install tabbable
Импорт в проект:
import { tabbable } from 'tabbable';
Простейший пример получения всех фокусируемых элементов внутри контейнера:
const container = document.getElementById('form-container');
const focusableElements = tabbable(container);
console.log(focusableElements);
Результатом является массив DOM-элементов, упорядоченных по естественному порядку табуляции. Это удобно для реализации циклической навигации, модальных окон и кастомных компонентов управления фокусом.
Функция tabbable поддерживает объект конфигурации с
несколькими ключевыми параметрами:
display,
visibility и opacity.Пример с пользовательской проверкой видимости:
const visibleElements = tabbable(container, {
displayCheck: (node) => window.getComputedStyle(node).visibility !== 'hidden'
});
Tabbable корректно обрабатывает элементы внутри Shadow
DOM, что позволяет создавать доступные веб-компоненты.
Использование параметра getShadowRoot гарантирует, что
вложенные элементы будут учитываться:
const focusableInShadow = tabbable(document.body, {
getShadowRoot: (node) => node.shadowRoot
});
Библиотека рекурсивно обходит все вложенные тени, собирая элементы в порядке табуляции.
Tabbable учитывает ARIA-атрибуты и CSS-свойства, которые могут скрывать элемент:
aria-hidden="true" исключает элемент из списка.display: none и visibility: hidden делают
элемент недоступным для фокуса.tabindex="-1" игнорируются при навигации по
клавише Tab, но могут быть сфокусированы программно
(element.focus()).const modal = document.getElementById('modal');
const focusable = tabbable(modal);
focusable[0].focus();
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
const first = focusable[0];
const last = focusable[focusable.length - 1];
if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
} else if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
}
}
});
Кастомные компоненты — кнопки, селекты и
выпадающие меню могут использовать tabbable для контроля
навигации и предотвращения выхода фокуса за пределы компонента.
Тестирование доступности — массив фокусируемых элементов помогает проверять порядок табуляции и выявлять элементы, которые неожиданно теряются из навигации.
tabbable в сочетании с логикой
ограничения фокуса при работе с модальными окнами или всплывающими
меню.disabled, hidden и
aria-hidden для исключения невидимых элементов.tabbable на больших
контейнерах в цикле, лучше кэшировать результат при неизменяемом
DOM.getShadowRoot, чтобы избежать потери элементов
в Shadow DOM.tabindex, чтобы
элементы с положительным tabindex не нарушали естественную
последовательность и доступность.Tabbable предоставляет надёжный механизм для управления фокусом, гарантируя соответствие стандартам доступности и упрощая защитное программирование в веб-приложениях. Его использование минимизирует ошибки в навигации и позволяет создавать интерфейсы, полностью контролируемые с клавиатуры.