Библиотека Focus-trap предназначена для управления фокусом внутри определённых элементов DOM, таких как модальные окна, всплывающие панели или диалоговые формы. Основная задача — запретить пользователю перемещаться за пределы указанной зоны с помощью клавиши Tab, обеспечивая доступность интерфейса и корректное поведение клавиатуры.
Focus-trap распространяется как npm-пакет и поддерживает современные сборщики:
npm install focus-trap
Для использования в проекте с ES-модулями:
import { createFocusTrap } from 'focus-trap';
В случае использования через тег <script> в
браузере доступен глобальный объект focusTrap.
Фокустрап создаётся с помощью функции createFocusTrap,
которой передаётся DOM-элемент и объект опций:
const modal = document.getElementById('modal');
const trap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
allowOutsideClick: true,
});
Ключевые параметры:
Для активации:
trap.activate();
Для деактивации:
trap.deactivate();
Focus-trap предоставляет гибкие настройки поведения:
const trap = createFocusTrap(modal, {
initialFocus: '#modal-input'
});
Можно передать селектор, функцию, возвращающую элемент, либо элемент напрямую.
initialFocus недоступен:fallbackFocus: modal.querySelector('button')
returnFocusOnDeactivate: true
tabbable, используемой внутри focus-trap для вычисления
фокусируемых элементов:tabbableOptions: { displayCheck: 'none' }
В Svelte-файлах фокустрап удобно использовать с реактивными
привязками и жизненным циклом компонента (onMount,
onDestroy):
<script>
import { onMount, onDestroy } from 'svelte';
import { createFocusTrap } from 'focus-trap';
let modal;
let trap;
onMount(() => {
trap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#first-input',
returnFocusOnDeactivate: true
});
});
function openModal() {
trap.activate();
}
function closeModal() {
trap.deactivate();
}
onDestroy(() => {
if (trap) trap.deactivate();
});
</script>
<div bind:this={modal} class="modal">
<input id="first-input" type="text">
<button on:click={closeModal}>Закрыть</button>
</div>
<button on:click={openModal}>Открыть модальное окно</button>
bind:this позволяет получить прямой
доступ к DOM-элементу Svelte.onMount гарантирует, что элемент существует в DOM до
создания фокустрапа.onDestroy предотвращает утечки памяти при удалении
компонента.Если внутри модального окна появляются новые фокусируемые элементы после активации, focus-trap автоматически их учитывает, поскольку библиотека пересчитывает tabbable-элементы при каждой попытке перемещения фокуса. Для ручного обновления можно вызвать:
trap.updateContainerElements();
Focus-trap позволяет создавать несколько независимых зон, каждая со своими настройками. При активации одного из фокустрапов другой может оставаться неактивным или быть деактивирован автоматически:
const firstTrap = createFocusTrap(firstModal);
const secondTrap = createFocusTrap(secondModal);
firstTrap.activate(); // второй пока не активен
secondTrap.activate(); // первый деактивируется автоматически
allowOutsideClick можно разрешить клики за пределами
внутреннего модального окна, не деактивируя родительский фокустрап.:focus и :focus-visible для визуальной
подсветки активного элемента.returnFocusOnDeactivate: true для
сохранения логики навигации клавиатурой.initialFocus для первого интерактивного
элемента, чтобы избежать «потерянного» фокуса при открытии модального
окна.Focus-trap обеспечивает полноценное управление клавиатурным фокусом, делает интерфейсы доступными и безопасными для пользователей с навигацией без мыши, и отлично интегрируется с современными фреймворками, такими как Svelte.