Библиотека Focus-trap предназначена для управления фокусом внутри определённого контейнера в веб-приложении. Она особенно полезна при работе с модальными окнами, всплывающими меню, всплывающими подсказками и другими интерактивными элементами, где важно ограничить перемещение клавиатурного фокуса.
Фокус в браузере по умолчанию может уходить за пределы активного компонента. Focus-trap создаёт так называемую «ловушку фокуса», которая удерживает фокус внутри указанного элемента до тех пор, пока ловушка не будет отключена.
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const trap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true
});
trap.activate();
Ключевые параметры:
escapeDeactivates — определяет, можно ли деактивировать
ловушку с помощью клавиши Esc.clickOutsideDeactivates — позволяет пользователю
закрывать ловушку кликом вне её области.returnFocusOnDeactivate — после деактивации фокус
возвращается к элементу, который был активен до активации ловушки.Даже с активной ловушкой фокуса, существуют ситуации, когда фокус может покинуть контейнер:
Асинхронное изменение DOM Если элементы внутри
ловушки удаляются или заменяются динамически, фокус может «уплыть» на
другой элемент вне контейнера. Для предотвращения этого важно
использовать updateContainerElements() или
реинициализировать ловушку после изменений.
Модальные окна и вложенные ловушки При наличии нескольких модальных окон, активных одновременно, последняя активированная ловушка получает приоритет. Фокус может перейти к предыдущей ловушке, если текущая деактивируется некорректно.
Элементы с display: none или
visibility: hidden Если текущий фокус находится на
элементе, который скрывается, библиотека автоматически переносит фокус
на первый доступный элемент. При отсутствии доступных элементов фокус
уходит за пределы контейнера.
Неподдерживаемые элементы Некоторые элементы,
такие как <div> без атрибута tabindex,
не могут принимать фокус. Если ловушка содержит только такие элементы,
фокус будет уходить к родительскому элементу или к body.
Focus-trap предоставляет API для точного контроля:
activate(options) — активирует ловушку с возможностью
передачи временных опций.deactivate(options) — отключает ловушку. Опция
returnFocus управляет возвратом фокуса.pause() и unpause() — временно
приостанавливают управление фокусом, полезно при показе подсказок или
всплывающих панелей внутри модального окна.Пример корректной обработки ухода фокуса:
trap.activate();
// Обновление ловушки после динамических изменений
modal.addEventListener('DOMNodeInserted', () => {
trap.updateContainerElements();
});
// При закрытии модального окна
document.getElementById('closeButton').addEventListener('click', () => {
trap.deactivate({ returnFocus: true });
});
returnFocusOnDeactivate, чтобы
пользователь не терял ориентир после закрытия модального окна.tabindex="0".clickOutsideDeactivates
осторожно: в сложных интерфейсах это может привести к неожиданному уходу
фокуса.Для выявления причин, по которым фокус покидает ловушку:
modal.addEventListener('focusin', e => console.log('Focus in:', e.target));
modal.addEventListener('focusout', e => console.log('Focus out:', e.target));
document.activeElement).Фокус в ловушке может уходить только при нарушении условий доступности элементов или некорректной активации/деактивации. Использование встроенных методов Focus-trap, корректная настройка опций и динамическое обновление элементов контейнера позволяют полностью контролировать перемещение фокуса и предотвращать его непреднамеренный уход за пределы ловушки.