Библиотека Focus-trap предназначена для управления фокусом внутри модальных окон, диалогов и других интерактивных компонентов, ограничивая перемещение по клавиатуре только определённой областью. Это обеспечивает корректное поведение для пользователей с клавиатурой и улучшает доступность (a11y).
Одним из ключевых механизмов является автоматическое определение фокусируемых элементов, которое позволяет библиотеке динамически формировать список элементов, доступных для фокуса, без ручного указания.
Focus-trap использует внутреннюю функцию, которая ищет все элементы внутри контейнера, подходящие для фокуса. Критерии включают:
Селекторы интерактивных элементов:
<a> с атрибутом href<button><input><select><textarea><iframe>[tabindex][contenteditable]Состояние доступности элемента:
offsetParent !== null)disabled !== true)tabindex ≥ 0 учитывается для управления
порядком фокусаПорядок обхода:
tabindex обрабатываются
первыми в порядке возрастания значения tabindextabindex или с tabindex="0"
идут далее в DOM-порядкеtabindex < 0 игнорируются, поскольку они
недоступны для клавиатурного фокусаЭта система обеспечивает корректный порядок навигации при использовании клавиши Tab и обратной навигации через Shift+Tab.
Focus-trap предоставляет опции, которые позволяют изменять поведение поиска фокусируемых элементов:
initialFocus – элемент, который
получает фокус при активации трапа. Может быть CSS-селектором, DOM-узлом
или функцией, возвращающей элемент. Если не указан, библиотека
автоматически фокусируется на первом доступном элементе.
fallbackFocus – элемент, на который
фокус перейдет, если первый фокусируемый элемент недоступен. Важен для
динамически изменяемого контента.
allowOutsideClick – позволяет
кликам вне трапа не нарушать управление фокусом, при этом автоматическое
определение фокусируемых элементов продолжается в пределах
контейнера.
Пример инициализации:
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const trap = createFocusTrap(modal, {
initialFocus: '#modal input:first-of-type',
fallbackFocus: '#modal button.close',
allowOutsideClick: true
});
trap.activate();
В этом примере первый фокус назначается на первый
<input> внутри модального окна, а если его нет — на
кнопку закрытия.
Focus-trap способен корректно работать с динамическим содержимым, например, при добавлении или удалении элементов в DOM:
checkCanFocusTrap может быть использована для
асинхронной проверки доступности элемента перед фокусировкойtrap.updateContainerElements(); // пересчитать фокусируемые элементы
Метод особенно полезен для SPA и компонентов с ленивой загрузкой, где элементы появляются после активации модального окна.
Невидимые элементы: даже если элемент
присутствует в DOM, он игнорируется, если display: none,
visibility: hidden или opacity: 0 при
pointer-events: none.
Элементы с tabindex="-1": могут
быть выбраны как initialFocus или
fallbackFocus, но не входят в автоматический обход при
обычной навигации через Tab.
Смешанные табиндексы: если в контейнере есть
элементы с положительными и нулевыми tabindex, порядок
обхода формируется следующим образом: сначала элементы с положительными
значениями по возрастанию, затем элементы без tabindex или
с tabindex="0".
Shadow DOM: фокусируемые элементы внутри Shadow DOM корректно обнаруживаются, если контейнер трапа включает shadow root в качестве корня поиска.
fallbackFocus, чтобы избежать
ситуации, когда фокус “теряется” при отсутствии доступных
элементов.initialFocus для контроля, какой элемент
должен быть выделен при открытии модального окна.updateContainerElements или повторно активировать трап,
чтобы список фокусируемых элементов соответствовал текущему состоянию
DOM.tabindex вручную без необходимости —
автоматическое определение учитывает стандартные интерактивные элементы
и обеспечивает правильный порядок обхода.Эти механизмы делают Focus-trap универсальным инструментом для управления фокусом, минимизируя ручное вмешательство и повышая доступность интерфейсов.