Focus-trap — это библиотека для управления фокусом внутри определённых областей веб-страницы. Основная задача — удерживать фокус внутри модального окна, диалогового окна или другой интерактивной зоны, предотвращая переход на элементы за пределами этого контейнера с помощью клавиши Tab или Shift+Tab. Это критически важно для доступности (accessibility) и соответствия стандартам WCAG, так как позволяет пользователям клавиатуры и вспомогательных технологий корректно взаимодействовать с интерфейсом.
Фокус в DOM управляется свойством
document.activeElement. Focus-trap автоматически
перехватывает события клавиатуры и изменяет порядок фокусировки, чтобы
фокус оставался внутри целевой области.
Библиотека распространяется через npm и CDN.
npm install focus-trap
Для использования через ES-модули:
import { createFocusTrap } from 'focus-trap';
Для классического подключения через CDN:
<script src="https://unpkg.com/focus-trap@6/dist/focus-trap.min.js"></script>
Focus-trap создается с помощью функции createFocusTrap,
в которую передается контейнер DOM и набор опций.
const modal = document.getElementById('alert-dialog');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
allowOutsideClick: true,
fallbackFocus: modal
});
Ключевые опции:
true, нажатие
клавиши Escape деактивирует фокус-трап.Focus-trap имеет методы управления:
returnFocusOnDeactivate).focusTrap.activate();
document.getElementById('close-btn').addEventListener('click', () => {
focusTrap.deactivate();
});
Опция returnFocusOnDeactivate позволяет
контролировать, возвращается ли фокус на элемент, который его
инициировал.
const focusTrap = createFocusTrap(modal, {
returnFocusOnDeactivate: true
});
Alert dialog — это модальное окно, требующее немедленного внимания пользователя. Фокус должен быть строго внутри диалога до момента его закрытия.
Пример структуры HTML:
<div id="alert-dialog" role="alertdialog" aria-modal="true" aria-labelledby="dialog-title" aria-describedby="dialog-desc">
<h2 id="dialog-title">Внимание</h2>
<p id="dialog-desc">Произошла ошибка при сохранении данных.</p>
<button id="confirm-btn">Ок</button>
</div>
JavaScript для интеграции с Focus-trap:
const dialog = document.getElementById('alert-dialog');
const confirmBtn = document.getElementById('confirm-btn');
const focusTrap = createFocusTrap(dialog, {
escapeDeactivates: true,
clickOutsideDeactivates: false,
fallbackFocus: confirmBtn,
onActivate: () => dialog.style.display = 'block',
onDeactivate: () => dialog.style.display = 'none'
});
document.getElementById('show-dialog').addEventListener('click', () => {
focusTrap.activate();
});
confirmBtn.addEventListener('click', () => {
focusTrap.deactivate();
});
Для alert dialog критично использовать правильные ARIA-атрибуты:
Focus-trap корректно взаимодействует с ARIA, удерживая фокус внутри диалога и предотвращая взаимодействие с фоновыми элементами.
fallbackFocus, чтобы избежать ситуации
без фокусируемых элементов.clickOutsideDeactivates, чтобы пользователь был вынужден
взаимодействовать с самим диалогом.