Tabbable — это специализированная библиотека на
JavaScript, предназначенная для определения элементов страницы, которые
могут получать фокус через клавишу Tab. Она играет
ключевую роль в обеспечении доступности интерфейсов, позволяя корректно
управлять последовательностью фокуса и визуальной обратной связью при
навигации с клавиатуры.
Библиотека анализирует DOM и возвращает список
элементов, которые удовлетворяют условиям
tabbable: видимые, интерактивные, не заблокированные
через disabled или aria-hidden. Основной
экспорт библиотеки — функция tabbable(container, options),
где container — корневой элемент для поиска, а
options позволяют управлять фильтрацией.
import { tabbable } from 'tabbable';
const elements = tabbable(document.body);
console.log(elements); // массив всех tabbable-элементов в body
Ключевые моменты:
display: none,
visibility: hidden).tabindex="-1" исключаются.<a>,
<button>, <input>,
<textarea>, <select>.Порядок, в котором элементы получают фокус при нажатии Tab,
определяется DOM-порядком и значением атрибута
tabindex. Tabbable учитывает:
tabindex: элемент
получает приоритет.tabindex: элемент следует
стандартному DOM-порядку.tabindex: элемент
исключается из последовательности фокуса.<button tabindex="2">Второй</button>
<button tabindex="1">Первый</button>
<button>Третий</button>
const elements = tabbable(document.body);
elements.forEach(el => console.log(el.textContent));
// Выведет: Первый, Второй, Третий
Tabbable автоматически сортирует элементы по
tabindex и DOM-позиции, обеспечивая корректную навигацию
без дополнительных скриптов.
Важный аспект — визуальное выделение элементов,
получающих фокус. CSS-псевдокласс :focus позволяет
стилизовать элементы:
button:focus, input:focus {
outline: 3px solid #1976d2;
outline-offset: 2px;
}
Рекомендации по визуальной обратной связи:
transition..button {
transition: box-shadow 0.2s ease-in-out;
}
.button:focus {
box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.5);
}
Tabbable возвращает элементы, на которые можно программно установить
фокус с помощью element.focus(). Это полезно для создания
циклической навигации или модальных
окон.
import { tabbable } from 'tabbable';
const modal = document.querySelector('.modal');
const focusableElements = tabbable(modal);
focusableElements[0].focus(); // установка фокуса на первый элемент модалки
// Циклическая навигация
modal.addEventListener('keydown', e => {
if (e.key === 'Tab') {
const first = focusableElements[0];
const last = focusableElements[focusableElements.length - 1];
if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
} else if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
}
}
});
Такой подход обеспечивает полностью управляемый фокус, улучшает UX и поддерживает стандарты доступности WCAG.
Tabbable поддерживает настройку через опцию
includeContainer, которая позволяет включать корневой
элемент в результирующий список, если он сам tabbable:
const elements = tabbable(modal, { includeContainer: true });
Можно комбинировать с дополнительной фильтрацией по селекторам:
const elements = tabbable(document.body).filter(el => el.tagName === 'BUTTON');
Это позволяет строить специализированные панели управления фокусом, например, только для кнопок в модальных окнах или интерактивных виджетах.
Для элементов без естественного фокуса (div,
span) можно использовать tabindex="0".
Tabbable корректно учитывает такие элементы:
<div class="custom" tabindex="0">Фокусируемый блок</div>
const elements = tabbable(document.body);
elements.includes(document.querySelector('.custom')); // true
Важно помнить:
tabindex="-1" исключает элемент из последовательности,
но позволяет программно фокусироваться.Tabbable часто используется вместе с компонентными библиотеками, например React или Vue, для реализации модальных окон, вкладок и аккордеонов. Основные паттерны:
// Пример для React-попапа
useEffect(() => {
if (isOpen) {
const focusableEls = tabbable(modalRef.current);
focusableEls[0].focus();
}
}, [isOpen]);
Использование Tabbable напрямую повышает доступность интерфейса:
aria-* атрибутами обеспечивается
семантическая ясность и поддержка вспомогательных технологий.Эта библиотека является основой для построения управляемого и предсказуемого фокуса на веб-странице, обеспечивая как техническую корректность, так и визуальную обратную связь, критически важную для доступности интерфейсов.