Библиотека Focus-trap предназначена для управления фокусом внутри определённого элемента DOM. Основная цель — создание интерактивных областей, таких как модальные окна, всплывающие панели и панели с настройками, где пользовательский фокус клавиатуры ограничен внутри заданного контейнера. Это предотвращает случайное перемещение фокуса на элементы страницы, находящиеся за пределами активной зоны.
Focus-trap работает на основе нескольких ключевых принципов:
Tab и Shift+Tab для
циклической навигации по фокусируемым элементам внутри контейнера.Библиотека распространяется через npm:
npm install focus-trap
После установки можно импортировать её в проект:
import { createFocusTrap } from 'focus-trap';
Для проектов, использующих CommonJS:
const { createFocusTrap } = require('focus-trap');
Фокус-трап создается для конкретного контейнера. В качестве примера
используется модальное окно с идентификатором modal:
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#first-input',
fallbackFocus: modal,
});
Ключевые опции:
true, нажатие
клавиши Escape деактивирует трап.initialFocus не найден.Фокус-трап необходимо активировать после создания:
focusTrap.activate();
Для временного отключения используется метод:
focusTrap.deactivate();
При деактивации фокус возвращается на элемент, который был активен до активации трапа, если не задано иное.
Focus-trap автоматически обрабатывает нажатия Tab и
Shift+Tab. Цикличная навигация обеспечивается за счёт
вычисления всех фокусируемых элементов внутри
контейнера:
<a> с href<button><input>, <select>,
<textarea>[tabindex], кроме tabindex="-1"Если фокус находится на последнем элементе и пользователь нажимает
Tab, фокус перемещается на первый элемент. При обратной
навигации (Shift+Tab) аналогично с последним элементом.
Focus-trap поддерживает элементы, которые появляются в DOM после
активации трапа. Для этого используется метод
updateTabbables():
focusTrap.updateTabbables();
Этот метод пересчитывает список доступных элементов для фокуса, что необходимо при динамическом рендеринге форм или списков внутри контейнера.
Библиотека позволяет задавать пользовательские коллбэки для ключевых событий:
const focusTrap = createFocusTrap(modal, {
onActivate: () => console.log('Трап активирован'),
onDeactivate: () => console.log('Трап деактивирован'),
});
activate().deactivate().Дополнительно можно реагировать на клики вне контейнера и нажатия
клавиши Escape через опции
clickOutsideDeactivates и
escapeDeactivates.
Для модального окна с кнопкой открытия и закрытия пример выглядит так:
const openButton = document.getElementById('open-modal');
const closeButton = document.getElementById('close-modal');
openButton.addEventListener('click', () => {
focusTrap.activate();
modal.style.display = 'block';
});
closeButton.addEventListener('click', () => {
focusTrap.deactivate();
modal.style.display = 'none';
});
Такой подход обеспечивает:
keydown.initialFocus на первый логический
элемент формы или интерактивного блока.aria-hidden для скрытия элементов за
пределами активного трапа.Focus-trap поддерживает вложенные трапы. В этом случае активация вложенного трапа временно блокирует родительский, а после деактивации возвращает управление обратно. Это полезно для многоуровневых модальных интерфейсов и выпадающих меню.
Для программного контроля доступна опция
returnFocusOnDeactivate, которая позволяет выбрать, куда
вернётся фокус после закрытия трапа:
returnFocusOnDeactivate: document.getElementById('custom-focus')
Если модальное окно или панель подгружается динамически, необходимо
убедиться, что активация трапа происходит после вставки
элементов в DOM. В противном случае initialFocus может не
сработать, и фокус будет установлен на fallbackFocus.
fetch('/form.html')
.then(res => res.text())
.then(html => {
modal.innerHTML = html;
focusTrap.activate();
});
Фокус-трап обеспечивает надежное управление фокусом, улучшает доступность и упрощает взаимодействие с модальными и интерактивными элементами страницы, минимизируя необходимость ручного контроля клавиатурной навигации.