focus-trap — это библиотека для управления фокусом
клавиатуры внутри определённой области DOM. Она позволяет ограничивать
перемещение фокуса пользователем в пределах заданного контейнера, что
особенно важно для модальных окон, всплывающих панелей, диалогов и
других интерактивных элементов интерфейса.
Главная цель — улучшение доступности (accessibility,
a11y), предотвращение выхода фокуса за пределы интерфейсного блока при
навигации с клавиатуры. Без focus-trap пользователь, перемещаясь по
элементам с помощью клавиши Tab, может случайно покинуть
модальное окно или панель, что нарушает логику интерфейса и ухудшает
пользовательский опыт.
Библиотека доступна через npm и Yarn:
npm install focus-trap
или
yarn add focus-trap
Для использования в браузере можно подключить через CDN:
<script src="https://unpkg.com/focus-trap/dist/focus-trap.min.js"></script>
После подключения создаётся объект trap с указанием контейнера, в котором необходимо зафиксировать фокус.
Базовый синтаксис создания фокус-трэпа:
import { createFocusTrap } from 'focus-trap';
const modal = document.querySelector('#modal');
const trap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
fallbackFocus: modal
});
Ключевые параметры:
escapeDeactivates — при нажатии клавиши
Escape фокус-трэп отключается.clickOutsideDeactivates — клик вне контейнера выводит
фокус из трэпа.fallbackFocus — элемент, на который будет установлен
фокус, если внутри контейнера нет подходящих элементов для фокуса.Для активации:
trap.activate();
Для деактивации:
trap.deactivate();
Focus-trap наиболее часто используется с модальными окнами. Основная задача — удерживать фокус внутри модального окна до момента его закрытия. Это предотвращает потерю контекста и обеспечивает корректную работу клавиатурной навигации.
Пример управления модальным окном:
const openButton = document.querySelector('#openModal');
const closeButton = document.querySelector('#closeModal');
const modal = document.querySelector('#modal');
const trap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true
});
openButton.addEventListener('click', () => {
modal.style.display = 'block';
trap.activate();
});
closeButton.addEventListener('click', () => {
trap.deactivate();
modal.style.display = 'none';
});
Focus-trap позволяет тонко настраивать поведение через дополнительные опции:
initialFocus — элемент, который
получает фокус при активации трэпа.allowOutsideClick — позволяет кликам
по элементам вне контейнера взаимодействовать с ними, не деактивируя
трэп.returnFocusOnDeactivate — возвращает
фокус на элемент, который был активен до активации трэпа.tabbableOptions — конфигурация
библиотеки tabbable, используемой внутри focus-trap для
определения элементов, доступных для фокуса.Пример с initialFocus:
const trap = createFocusTrap(modal, {
initialFocus: '#modalInput',
escapeDeactivates: true
});
Focus-trap можно интегрировать с асинхронными действиями и
динамически создаваемыми элементами. При этом важно вызывать
updateTabbableNodes() после изменения DOM, чтобы трэп
корректно определял доступные элементы для фокуса:
trap.updateTabbableNodes();
Также можно комбинировать несколько трэпов, управляя их активацией и деактивацией, например, при вложенных модальных окнах:
const parentTrap = createFocusTrap(parentModal);
const childTrap = createFocusTrap(childModal);
parentTrap.activate();
childTrap.activate();
childTrap.deactivate(); // возвращает фокус в parentTrap
tabindex — focus-trap
фокусируется только на tabbable-элементах. Если в контейнере нет
интерактивных элементов, необходимо задать tabindex="0" для
fallback-фокуса.updateTabbableNodes().Focus-trap легко интегрируется с популярными фреймворками:
focus-trap-react,
оборачивая модальные компоненты.v-if или v-show, создавая трэп при
монтировании компонента.Focus-trap усиливает доступность интерфейсов, но для полной compliance важно:
aria-modal="true" для модальных окон.aria-labelledby и
aria-describedby.Focus-trap является базовым инструментом для создания безопасных и доступных интерактивных интерфейсов, удерживая пользователя в контексте и предотвращая случайное уход фокуса за пределы ключевых элементов. Его гибкость позволяет управлять как простыми модальными окнами, так и сложными вложенными интерфейсами.