Библиотека Focus-trap предназначена для управления фокусом внутри заданного DOM-элемента, предотвращая уход фокуса за его пределы. Основная цель — обеспечить корректную навигацию с клавиатуры, особенно в модальных окнах, всплывающих панелях и интерактивных компонентах.
Focus-trap создаёт ловушку фокуса, автоматически переводя фокус на первый интерактивный элемент при активации и возвращая его на исходный элемент при деактивации.
По умолчанию Focus-trap обрабатывает следующие сценарии:
Для сложных интерфейсов требуется переопределение стандартного поведения через настройки при инициализации.
Focus-trap позволяет задавать элемент, который будет получать фокус
при активации, через параметр initialFocus.
const trap = createFocusTrap('#modal', {
initialFocus: '#modal-input'
});
trap.activate();
initialFocus не указан, фокус устанавливается на
первый доступный интерактивный элемент.const trap = createFocusTrap('#modal', {
initialFocus: () => document.querySelector('.special-button')
});
Это позволяет выбирать элемент на основе текущего состояния интерфейса.
Иногда требуется, чтобы определённые элементы внутри ловушки
не участвовали в цикле фокуса. Для этого используется
опция allowOutsideClick и метод setReturnFocus
совместно с кастомной фильтрацией:
const trap = createFocusTrap('#modal', {
onActivate: () => console.log('Trap активирован'),
tabbableOptions: {
displayCheck: 'none' // исключает скрытые элементы
}
});
Ключевой момент: tabbableOptions
позволяет управлять тем, какие элементы считаются интерактивными. Это
критично для сложных модальных окон с динамическим контентом.
Focus-trap по умолчанию деактивируется при нажатии
Escape. Для изменения этого поведения используется опция
onDeactivate и escapeDeactivates:
const trap = createFocusTrap('#modal', {
escapeDeactivates: false, // блокировка стандартного закрытия
onKeyDown: (event) => {
if (event.key === 'Escape') {
console.log('Escape нажат, но ловушка активна');
// Дополнительная логика вместо закрытия
}
}
});
Это позволяет внедрять кастомные реакции на нажатие клавиш, не нарушая общий цикл фокусировки.
Возврат фокуса на элемент, вызвавший активацию, выполняется через
опцию setReturnFocus. Можно указать кастомный элемент или
полностью блокировать возврат:
const trap = createFocusTrap('#modal', {
setReturnFocus: false // фокус не возвращается
});
Если требуется перенаправление фокуса на другой элемент после деактивации:
const trap = createFocusTrap('#modal', {
setReturnFocus: '#next-button'
});
Для элементов, которые появляются динамически (например, после
AJAX-запроса), важно переопределить initialFocus через
функцию, чтобы фокус устанавливался только после рендеринга:
const trap = createFocusTrap('#modal', {
initialFocus: () => document.querySelector('.dynamic-input')
});
Focus-trap гарантирует корректное определение интерактивных элементов даже в динамически обновляемых контейнерах.
По умолчанию фокус цикличен: Tab после последнего элемента возвращает
фокус на первый. Для изменения этого поведения используется опция
fallbackFocus:
const trap = createFocusTrap('#modal', {
fallbackFocus: '#modal' // фокус возвращается на контейнер
});
Это полезно для нестандартных интерфейсов, где нет явного первого или последнего элемента.
Focus-trap предоставляет хуки:
onActivate — вызывается при активации ловушки.onDeactivate — вызывается при деактивации.onPostActivate / onPostDeactivate —
позволяют работать после установки или снятия фокуса.Пример:
const trap = createFocusTrap('#modal', {
onActivate: () => console.log('Активировано'),
onDeactivate: () => console.log('Деактивировано')
});
Эти события позволяют интегрировать фокус-ловушку с анимациями и сложной логикой интерфейса.
Переопределение поведения Focus-trap сводится к правильной настройке
опций при инициализации: initialFocus,
tabbableOptions, escapeDeactivates,
setReturnFocus и хуков событий. Это обеспечивает гибкое
управление фокусом в динамических и интерактивных интерфейсах, позволяя
строить сложные модальные окна, панели и диалоговые компоненты с
безопасной и предсказуемой клавиатурной навигацией.