Библиотека Focus-trap предназначена для управления фокусом в веб-приложениях, обеспечивая его замыкание внутри заданного контейнера. Это критически важно для создания доступных интерфейсов, соответствующих требованиям WCAG, особенно при работе с модальными окнами, всплывающими подсказками и кастомными диалогами.
При активации фокус-трэпа элементы внутри контейнера становятся циклической последовательностью фокуса: переход с последнего элемента на первый и наоборот. Это предотвращает случайное перемещение фокуса за пределы активной зоны и обеспечивает предсказуемое поведение для пользователей с клавиатурой и вспомогательными технологиями.
Установка через npm:
npm install focus-trap
Или подключение через CDN:
<script src="https://unpkg.com/focus-trap/dist/focus-trap.min.js"></script>
Создание и активация простого фокус-трэпа:
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
});
document.getElementById('openModal').addEventListener('click', () => {
focusTrap.activate();
});
Ключевые параметры:
escapeDeactivates: позволяет закрывать фокус-трэп по
клавише Esc.clickOutsideDeactivates: позволяет деактивировать
фокус-трэп при клике вне контейнера.initialFocus: определяет элемент, который получит фокус
при активации.fallbackFocus: элемент, на который фокус вернется, если
initialFocus отсутствует.Для соответствия WCAG 2.1, модальные окна и всплывающие диалоги должны быть правильно размечены с помощью ARIA-атрибутов:
role="dialog" или role="alertdialog" на
контейнере.aria-modal="true" для обозначения блокировки фокуса на
фоне.aria-labelledby и aria-describedby для
связи с заголовком и описанием.Фокус-трэп не управляет этими атрибутами автоматически, поэтому их нужно добавлять вручную. Пример:
<div id="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-describedby="modalDesc">
<h2 id="modalTitle">Заголовок модального окна</h2>
<p id="modalDesc">Описание содержания модального окна.</p>
<button id="closeModal">Закрыть</button>
</div>
Dynamic Elements — фокус-трэп корректно обрабатывает динамически добавляемые элементы. Если новые интерактивные элементы появляются после активации, они автоматически включаются в цикл фокуса.
Nested Traps — поддержка вложенных фокус-трэпов позволяет создавать многоуровневые интерфейсы. Вложенный трап активируется при открытии поддиалога, временно приостанавливая родительский.
Custom Return Focus — после деактивации фокус возвращается на элемент, который инициировал модальное окно. Можно задать вручную:
const focusTrap = createFocusTrap(modal, {
onDeactivate: () => {
document.getElementById('openModal').focus();
}
});
Для соответствия WCAG 2.1 важно, чтобы все интерактивные элементы были доступными через клавиатуру и логически выстроены в DOM, а фокус-трэп обеспечивал непрерывную и предсказуемую навигацию.
display: none или visibility: hidden
автоматически игнорируются.Важно визуально обозначать фокус с помощью стилей:
button:focus, a:focus {
outline: 2px solid #005fcc;
outline-offset: 2px;
}
Эта практика повышает доступность для пользователей с ограниченным зрением и соответствует рекомендациям WCAG 2.1, раздел 2.4.7 (Focus Visible).
Фокус-трэп становится фундаментальным инструментом для создания доступных веб-интерфейсов, обеспечивая корректное замыкание фокуса и взаимодействие с клавиатурой. Правильное сочетание его с ARIA и визуальными индикаторами фокуса делает интерфейсы безопасными и удобными для всех пользователей.