Библиотека Focus-trap в JavaScript предназначена для управления фокусом внутри модальных окон, всплывающих панелей и других интерактивных областей. Основная задача — предотвратить выход фокуса за пределы контейнера, пока активен «трап» (trap). Это критично для обеспечения доступности (accessibility) и корректной работы клавиатурной навигации.
Focus-trap работает по принципу замыкания фокуса: при попытке перемещения клавишей Tab или Shift+Tab фокус циклично возвращается к элементам внутри контейнера.
Создание трапа осуществляется через функцию
createFocusTrap, которая принимает два параметра:
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const trap = createFocusTrap(modal, {
initialFocus: modal.querySelector('input'),
escapeDeactivates: true,
clickOutsideDeactivates: false,
});
Ключевые параметры:
initialFocus — элемент, который получает фокус при
активации трапа.escapeDeactivates — разрешает закрытие трапа клавишей
Escape.clickOutsideDeactivates — определяет, может ли клик вне
контейнера деактивировать трап.Активация и деактивация трапа выполняются методами
trap.activate() и trap.deactivate(). При
деактивации фокус возвращается на элемент, который был активен до
активации.
В последних версиях Focus-trap появились следующие ключевые изменения по сравнению с ранними версиями:
Поддержка асинхронной инициализации Теперь можно
задавать initialFocus через функцию, возвращающую элемент
или промис:
const trap = createFocusTrap(modal, {
initialFocus: () => document.querySelector('#async-input')
});Обновлённая обработка событий клика вне
контейнера Ранее clickOutsideDeactivates просто
отключал трап. Сейчас добавлена возможность передавать функцию для более
гибкой логики:
clickOutsideDeactivates: (event) => !event.target.closest('.no-deactivate')Поддержка вложенных трапов В новых версиях можно безопасно использовать несколько трапов внутри одного документа, при этом внутренний трап корректно захватывает фокус, не мешая внешнему.
Гибкая настройка возвращения фокуса Появился
параметр returnFocusOnDeactivate, который позволяет задать
конкретный элемент для возвращения фокуса или полностью отключить
возврат:
returnFocusOnDeactivate: document.getElementById('open-button')Focus-trap корректно обрабатывает динамически добавляемые элементы.
Для этого необходимо вызвать метод
updateContainerElements() после изменения содержимого
контейнера:
trap.updateContainerElements();
Это особенно важно для модальных окон, где элементы формы могут появляться или исчезать в процессе работы.
Для React, Vue или Angular рекомендуется инициализация трапа в момент монтирования компонента, с последующей деактивацией при размонтировании. Пример для React:
useEffect(() => {
const trap = createFocusTrap(modalRef.current);
trap.activate();
return () => trap.deactivate();
}, []);
Для динамически рендерящихся модальных окон важно учитывать, что контейнер должен существовать в DOM до активации трапа.
Focus-trap поддерживает дополнительные опции:
allowOutsideClick — разрешает клики вне трапа без
деактивации.tabbableOptions — передаёт настройки библиотеке tabbable для
управления видимостью и доступностью элементов.onActivate и onDeactivate — коллбэки,
вызываемые при активации и деактивации трапа.Пример:
const trap = createFocusTrap(modal, {
onActivate: () => console.log('Trap activated'),
onDeactivate: () => console.log('Trap deactivated'),
allowOutsideClick: true
});
initialFocus не поддерживал функции и промисы,
что ограничивало динамические сценарии.initialFocus, чтобы улучшить
доступность.escapeDeactivates для модальных окон.updateContainerElements().returnFocusOnDeactivate для управления
пользовательским опытом при закрытии модальных окон.Focus-trap обеспечивает надежное управление фокусом, повышает доступность и упрощает работу с интерактивными компонентами. Новые возможности делают библиотеку более гибкой и безопасной для современных приложений с динамическим контентом.