Focus-trap — это JavaScript-библиотека, предназначенная
для управления фокусом внутри определённого DOM-элемента. Основная цель
— ограничить навигацию с помощью клавиатуры (Tab, Shift+Tab)
выбранной областью, что особенно важно для модальных окон,
боковых панелей и всплывающих меню.
Библиотека обеспечивает:
Focus-trap можно использовать через npm или CDN:
npm install focus-trap
Или подключить через CDN:
<script src="https://unpkg.com/focus-trap/dist/focus-trap.min.js"></script>
Импорт через ES-модули:
import { createFocusTrap } from 'focus-trap';
Боковая панель обычно появляется поверх основного контента и должна блокировать взаимодействие с остальной страницей. Пример HTML-структуры:
<div id="sidebar" class="sidebar">
<button id="closeBtn">Закрыть</button>
<a href="#home">Главная</a>
<a href="#about">О проекте</a>
<a href="#contact">Контакты</a>
<input type="text" placeholder="Поиск">
</div>
<button id="openBtn">Открыть панель</button>
const sidebar = document.getElementById('sidebar');
const focusTrap = createFocusTrap(sidebar, {
// Перемещаем фокус на первый элемент при активации
initialFocus: '#closeBtn',
// Разрешаем выход по нажатию Escape
escapeDeactivates: true,
// Восстанавливаем фокус на кнопке открытия после закрытия
onDeactivate: () => document.getElementById('openBtn').focus(),
// Поддержка циклической навигации
tabbableOptions: { displayCheck: 'full' }
});
document.getElementById('openBtn').addEventListener('click', () => {
sidebar.style.display = 'block';
focusTrap.activate();
});
document.getElementById('closeBtn').addEventListener('click', () => {
sidebar.style.display = 'none';
focusTrap.deactivate();
});
initialFocus — элемент, который
получает фокус при активации trap. Можно передавать селектор или
DOM-элемент.
escapeDeactivates — булево значение,
определяющее возможность деактивации trap при нажатии Escape.
clickOutsideDeactivates — позволяет
закрывать trap при клике вне контейнера:
clickOutsideDeactivates: true
allowOutsideClick — если
true, клики вне контейнера проходят, но trap сохраняется
активным.
returnFocusOnDeactivate — автоматически
возвращает фокус на исходный элемент. Полезно для кнопок, которые
открывают боковую панель.
tabbableOptions — настройки для
элементов, которые могут быть доступны через Tab.
Если боковая панель подгружает элементы динамически, рекомендуется пересоздавать trap или обновлять список tabbable-элементов:
focusTrap.updateTabbables();
Это гарантирует корректную навигацию по новым элементам.
Для плавного появления панели с анимацией нужно активировать trap после завершения анимации, иначе фокус может установиться на скрытый элемент:
sidebar.classList.add('show'); // CSS-анимация
sidebar.addEventListener('transitionend', () => {
focusTrap.activate();
}, { once: true });
Для доступности рекомендуется использовать ARIA-атрибуты:
<div id="sidebar" role="dialog" aria-modal="true">
Focus-trap автоматически поддерживает ARIA-совместимые модальные
контейнеры, но явное указание aria-modal повышает
совместимость с экранными читалками.
display: none до активации
trap — элементы с display: none не могут получить
фокус.initialFocus для логичного
UX — обычно первый интерактивный элемент в панели или кнопка
закрытия.Focus-trap позволяет создать безопасную, предсказуемую и доступную боковую панель, гарантируя, что фокус пользователя всегда остаётся внутри интерактивной области и не теряется при переходах между элементами.