Focus-trap — это специализированная библиотека
JavaScript, предназначенная для управления фокусом внутри определённых
областей DOM. Она гарантирует, что клавиатурная навигация (Tab,
Shift+Tab) остаётся ограниченной заданной зоной, что особенно важно для
модальных окон, всплывающих панелей и интерактивных виджетов.
Библиотека реализует т.н. “ловушку фокуса”, предотвращая уход фокуса за пределы контейнера, пока он активен. Основной принцип: любые элементы, находящиеся вне зоны ловушки, становятся недоступными для клавиатуры до деактивации фокуса.
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
onActivate: () => modal.classList.add('is-active'),
onDeactivate: () => modal.classList.remove('is-active'),
});
document.getElementById('openModal').addEventListener('click', () => {
focusTrap.activate();
});
document.getElementById('closeModal').addEventListener('click', () => {
focusTrap.deactivate();
});
activate(options) — активирует ловушку фокуса. Опции могут включать:
returnFocus — возвращает фокус на исходный элемент
после деактивации.onActivate — коллбек при активации.onDeactivate — коллбек при деактивации.deactivate(options) — деактивирует ловушку.
Опции аналогичны activate, позволяют контролировать
возвращение фокуса.
pause() / unpause() — временно приостанавливает ловушку, позволяя пользователю покинуть контейнер без деактивации.
initialFocus — задаёт элемент, который получает фокус
при активации. Может быть селектором или функцией, возвращающей
элемент.fallbackFocus — элемент, на который будет установлен
фокус, если initialFocus недоступен.clickOutsideDeactivates — позволяет деактивировать
ловушку при клике за пределами контейнера.escapeDeactivates — деактивирует ловушку при нажатии
клавиши Escape.allowOutsideClick — разрешает клики вне контейнера, не
отключая ловушку полностью.tabbableOptions — объект с настройками для поиска
tabbable-элементов внутри контейнера.const focusTrap = createFocusTrap('#drawer', {
initialFocus: '#firstInput',
fallbackFocus: '#fallbackButton',
escapeDeactivates: true,
clickOutsideDeactivates: true
});
Focus-trap корректно работает с динамически изменяемым контентом.
Если внутри контейнера появляются новые tabbable-элементы, они
автоматически учитываются при навигации по Tab/Shift+Tab. Для вложенных
модальных окон можно создать отдельную ловушку для каждого слоя,
используя pause() на родительской ловушке при активации
дочерней.
const parentTrap = createFocusTrap('#parentModal');
const childTrap = createFocusTrap('#childModal', {
onActivate: () => parentTrap.pause(),
onDeactivate: () => parentTrap.unpause()
});
Focus-trap значительно повышает доступность интерфейсов:
aria-modal="true").<div id="modal" role="dialog" aria-modal="true">
<button id="closeModal">Закрыть</button>
<input type="text" placeholder="Имя">
</div>
initialFocus или
fallbackFocus, чтобы предотвратить потерю
фокуса.returnFocus: true при
деактивации модальных окон, чтобы пользователи возвращались к исходной
точке взаимодействия.clickOutsideDeactivates и
escapeDeactivates для удобства закрытия
всплывающих элементов.pause() для вложенных
интерфейсов.Без Focus-trap часто приходится вручную управлять фокусом через
обработчики событий keydown и методы
element.focus(). Это увеличивает вероятность ошибок,
особенно при динамическом контенте. Focus-trap абстрагирует эти задачи и
обеспечивает консистентное поведение во всех браузерах, включая
управление tabindex и обработку неактивных элементов.
Focus-trap легко интегрируется с React, Vue или Angular. Для React
есть отдельная обёртка focus-trap-react, позволяющая
управлять ловушкой через JSX и хуки жизненного цикла компонента.
import FocusTrap from 'focus-trap-react';
function Modal({ isOpen, onClose }) {
return (
<FocusTrap active={isOpen} focusTrapOptions={{ onDeactivate: onClose }}>
<div className="modal">
<button onCl ick={onClose}>Закрыть</button>
<input type="text" />
</div>
</FocusTrap>
);
}
Использование таких обёрток упрощает управление состоянием и обеспечивает совместимость с виртуальным DOM, автоматически синхронизируя фокус с компонентами.