Библиотека Focus-trap предназначена для управления фокусом внутри определённого контейнера. Основная задача — ограничение навигации по элементам интерфейса только элементами, находящимися внутри контейнера, что особенно важно для модальных окон, всплывающих подсказок и других интерактивных компонентов.
Основные принципы работы:
Для создания трепа используется функция
createFocusTrap:
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#first-input'
});
// Активировать фокус
focusTrap.activate();
// Деактивировать фокус
focusTrap.deactivate();
Ключевые параметры:
escapeDeactivates — позволяет закрывать треп нажатием
Escape.clickOutsideDeactivates — клик вне контейнера
деактивирует треп.initialFocus — задаёт элемент, на который будет
установлен фокус при активации.Focus-trap развивается с учётом современных стандартов браузеров, но
часто требуется поддержка старых версий, где focusin и
focusout могут работать некорректно.
Поддержка старых браузеров обеспечивается через следующие механизмы:
setTimeout и
document.activeElement — если событие
focusin не поддерживается, библиотека проверяет активный
элемент через таймер.Element.matches и
Node.contains — используются для корректного
определения, находится ли элемент внутри контейнера.tabindex — старые
браузеры могут неправильно обрабатывать tabindex="-1",
поэтому Focus-trap временно изменяет его на допустимое значение при
активации.Пример включения трепа с учётом обратной совместимости:
const focusTrap = createFocusTrap(modal, {
fallbackFocus: modal,
returnFocusOnDeactivate: true,
escapeDeactivates: true
});
fallbackFocus гарантирует, что даже если
initialFocus не найден, фокус попадёт на контейнер.returnFocusOnDeactivate обеспечивает возврат к
элементу, который был активен до активации трепа.В Internet Explorer 11 и ранних версиях Edge существуют специфические нюансы:
focusin на Shadow
DOM — библиотека создаёт дополнительный слушатель на корневом
документе.clickOutsideDeactivates — добавляется ручная
проверка координат клика.contenteditable —
Focus-trap игнорирует элементы с contenteditable по
умолчанию, чтобы избежать неожиданных переходов.Для интерфейсов с несколькими вложенными модальными окнами или
панелями используется allowOutsideClick и динамическое
управление activeTrap:
const outerTrap = createFocusTrap(outerModal);
const innerTrap = createFocusTrap(innerModal, {
onActivate: () => outerTrap.pause(),
onDeactivate: () => outerTrap.unpause()
});
pause() временно приостанавливает внешний треп,
позволяя внутреннему управлять фокусом.unpause() возвращает контроль внешнему трепу.Focus-trap поддерживает прямую интеграцию с популярными библиотеками:
focus-trap-react,
создаются обёртки компонентов, автоматически активирующие треп.fallbackFocus для совместимости с
браузерами, где initialFocus может не работать.returnFocusOnDeactivate для сохранения UX
при закрытии модального окна.pause() и unpause().Focus-trap обеспечивает надёжное управление фокусом даже в условиях ограниченной поддержки современных стандартов, позволяя создавать доступные и предсказуемые интерфейсы.