Библиотека Focus-trap предназначена для управления фокусом в веб-приложениях, обеспечивая замкнутую область взаимодействия для клавиатурной навигации. Она особенно полезна при создании модальных окон, диалогов, выпадающих меню и других компонентов, где пользовательский фокус должен оставаться внутри определённого элемента до завершения действия.
Для начала работы необходимо создать объект фокус-трапа, передав ему DOM-элемент, который будет ограничивать фокус:
import { createFocusTrap } from 'focus-trap';
const modal = document.querySelector('#modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
allowOutsideClick: true
});
Параметры и их значения:
escapeDeactivates — при нажатии клавиши Escape трап
деактивируется.clickOutsideDeactivates — клик вне элемента отключает
фокус-трап.allowOutsideClick — позволяет клики по элементам вне
трапа, не деактивируя его полностью.initialFocus — элемент, который получит фокус при
активации трапа.returnFocusOnDeactivate — возвращает фокус на элемент,
который его имел до активации.Фокус-трап может быть включен или выключен программно:
focusTrap.activate(); // Включение фокус-трапа
focusTrap.deactivate(); // Отключение фокус-трапа
При активации библиотека автоматически находит все фокусируемые элементы внутри контейнера и обеспечивает циклическую навигацию по ним при использовании клавиши Tab или Shift+Tab.
Для корректной работы фокус-трапа важно учитывать совместимость с
другими библиотеками, особенно inert-polyfill, которая
позволяет делать элементы недоступными для фокуса и взаимодействия.
inert-polyfill используется для отключения всех элементов
вне модального окна, что гарантирует, что пользователь не сможет
случайно взаимодействовать с контентом вне активного трапа.
Пример интеграции:
import 'wicg-inert';
const mainContent = document.querySelector('#main-content');
const modal = document.querySelector('#modal');
function openModal() {
mainContent.inert = true; // Отключаем основной контент
modal.removeAttribute('hidden');
focusTrap.activate();
}
function closeModal() {
mainContent.inert = false; // Возвращаем интерактивность основному контенту
modal.setAttribute('hidden', '');
focusTrap.deactivate();
}
Ключевые моменты интеграции:
inert полностью блокирует возможность
фокусировки и клика на элементы.inert = false при закрытии
окна, чтобы восстановить доступ к основному контенту.Focus-trap поддерживает опцию initialFocus, позволяющую
указать, какой элемент получит фокус сразу при активации:
const focusTrap = createFocusTrap(modal, {
initialFocus: '#modal-close-button'
});
Также можно использовать функцию, которая возвращает нужный элемент динамически:
initialFocus: () => document.querySelector('.dynamic-input')
Это удобно для диалогов с изменяющимся содержимым, где нужный элемент для фокуса определяется только после рендеринга.
Focus-trap позволяет реагировать на события выхода из трапа через
onDeactivate:
const focusTrap = createFocusTrap(modal, {
onDeactivate: () => console.log('Фокус-трап отключен')
});
Это используется для синхронизации с другими логическими компонентами приложения: закрытие модального окна, обновление состояния UI или повторная активация элементов вне трапа.
Focus-trap корректно работает с динамическим добавлением и удалением
элементов внутри контейнера. Однако при изменении DOM рекомендуется
переинициализировать трап или использовать методы
updateTabbableNodes() для пересчета фокусируемых
элементов.
focusTrap.updateTabbableNodes();
Это особенно актуально для списков с интерактивными элементами, загружаемых через AJAX или фреймворки типа React и Vue.
inert снижает риск утечки фокуса, но при
больших DOM-структурах стоит учитывать, что установка inert
на большие контейнеры может вызывать небольшие задержки.allowOutsideClick и clickOutsideDeactivates
для гибкого контроля поведения при кликах вне модального окна.Focus-trap работает во всех современных браузерах, но для старых
версий Safari и Edge рекомендуется использовать
inert-polyfill, так как они не поддерживают нативное
свойство inert. Полная совместимость обеспечивается
подключением скрипта:
<script src="https://unpkg.com/wicg-inert/dist/inert.min.js"></script>
Это гарантирует корректную работу focus-trap даже в браузерах без
поддержки inert.
Комбинация focus-trap и inert-polyfill обеспечивает полный контроль над фокусом в интерактивных интерфейсах. Она гарантирует:
Такой подход является стандартом при разработке доступных и удобных веб-компонентов.