Tabbable — это JavaScript-библиотека, предназначенная
для работы с элементами страницы, которые могут получать фокус при
навигации с помощью клавиши Tab. Основная задача библиотеки
— определить все интерактивные элементы, доступные для
пользователя через клавиатуру, что критично для доступности
веб-приложений (a11y).
Библиотека анализирует DOM и возвращает список элементов, которые
фокусируются естественным образом или с помощью
атрибута tabindex. Она учитывает такие свойства, как:
tabindexdisplay: none,
visibility: hidden)disabled,
aria-hidden)Базовая функция библиотеки — tabbable(container). Она
принимает контейнер DOM и возвращает массив всех элементов, доступных
для табуляции.
Пример использования:
import tabbable from 'tabbable';
const container = document.querySelector('#form-section');
const focusableElements = tabbable(container);
console.log(focusableElements);
Возвращаемый массив отсортирован в порядке визуального потока документа, что гарантирует естественный порядок табуляции для пользователя.
tabindextabindex определяет порядок фокусировки:
tabindex="0" — элемент включен в
обычный порядок табуляции.tabindex="-1" — элемент может
получить фокус программно, но не через Tab.tabindex="n" (n > 0) — элемент
получает приоритетную фокусировку, с меньшими числами
вначале.Tabbable корректно обрабатывает все три варианта,
создавая правильную последовательность фокуса, даже при
смешанном использовании положительных и отрицательных значений
tabindex.
Элементы, которые не видны пользователю, автоматически исключаются:
display: nonevisibility: hiddenopacity: 0 или
clip-path, не исключаются автоматически,
так как технически они доступны для фокуса, если это разрешено
браузером.Также библиотека учитывает aria-hidden="true",
предотвращая попадание скрытых от ассистивных технологий элементов в
массив tabbable.
Список встроенных элементов, которые tabbable считает
фокусируемыми по умолчанию:
<a> с href<button><input> (все типы, кроме
hidden)<select><textarea><iframe><audio> и <video> с атрибутом
controlsДля всех остальных элементов требуется явное указание
tabindex, чтобы их включить в последовательность
табуляции.
Для сложных UI-компонентов, таких как модальные окна, кастомные
селекты или карусели, tabbable позволяет:
Пример ограничения фокуса внутри модального окна:
const modal = document.querySelector('#modal');
const focusable = tabbable(modal);
let first = focusable[0];
let last = focusable[focusable.length - 1];
modal.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();
}
}
});
Tabbable использует рекурсивный обход
DOM, что делает алгоритм точным, но потенциально затратным на
больших страницах. Для оптимизации рекомендуется:
Библиотека поддерживает дополнительные опции:
getShadowRoot — для работы с теневыми
DOM.includeContainer — если требуется, чтобы сам контейнер
считался tabbable.tabbableOptions — позволяет добавлять кастомные
селекторы или фильтры для исключения/включения элементов.const focusableWithCustomFilter = tabbable(container, {
getShadowRoot: true,
includeContainer: false,
tabbableOptions: {
displayCheck: 'full' // или 'none', для строгой фильтрации видимости
}
});
Tabbable становится критическим инструментом для
разработки доступных интерфейсов и контроля последовательности
фокусировки, особенно в сложных динамических веб-приложениях.