Библиотека Focus-trap предназначена для управления
фокусом внутри модальных окон, диалогов, меню и других интерактивных
контейнеров, обеспечивая корректное поведение клавиатурной навигации.
Особое внимание уделяется элементам, которые скрыты с помощью CSS:
display: none и visibility: hidden. Понимание
различий между этими свойствами критично для корректной работы
Focus-trap.
display: none и visibility: hiddendisplay: none полностью удаляет
элемент из потока документа. Для браузера элемент считается
отсутствующим:
tabindex на таком элементе игнорируется.visibility: hidden скрывает элемент
визуально, но оставляет его в DOM и в потоке документа:
tabindex по умолчанию делает элемент недоступным для
клавиши Tab, но при явной установке tabindex="0" элемент
может получить фокус.Focus-trap опирается на метод
tabbable для определения всех элементов,
которые могут быть фокусированы. Основные правила:
display: none автоматически исключаются из
списка tabbable. Их нельзя выбрать клавишей Tab.visibility: hidden также по умолчанию
исключаются из табуляции, если не заданы явные
tabindex.import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
});
document.getElementById('openModal').addEventListener('click', () => {
modal.style.display = 'block';
focusTrap.activate();
});
document.getElementById('closeModal').addEventListener('click', () => {
modal.style.display = 'none';
focusTrap.deactivate();
});
display: none полностью убирает модальное окно из
DOM-потока, поэтому Focus-trap активируется только после отображения
(display: block).visibility: hiddenconst tooltip = document.getElementById('tooltip');
tooltip.style.visibility = 'hidden'; // скрыт визуально
// Элемент с tabindex="0" может быть фокусирован
tooltip.setAttribute('tabindex', '0');
const tooltipTrap = createFocusTrap(tooltip);
tooltipTrap.activate();
visibility: hidden может быть фокусирован при
наличии tabindex, но обычно такие элементы лучше скрывать с
display: none для предотвращения неожиданных переходов
фокуса.display: none для полного
исключения элемента из фокусируемой области. Особенно важно для
модальных окон и временных панелей.visibility: hidden
для исключения элемента из Focus-trap: без явного tabindex
элемент всё равно не будет участвовать в цикле, но это может создать
проблемы при динамическом изменении стилей.focusTrap.updateTabbableNodes().При динамическом отображении элементов внутри Focus-trap
(display: none → block) нужно учитывать:
updateTabbableNodes() позволяет
пересканировать контейнер и добавить новые интерактивные элементы в
цикл.focusTrap.updateTabbableNodes();
| Свойство | Влияние на Focus-trap | Рекомендация |
|---|---|---|
display: none |
Полностью исключает из фокуса | Использовать для скрытия модальных окон |
visibility: hidden |
Элемент визуально скрыт, но может быть фокусирован при tabindex | Использовать с осторожностью, лучше избегать |
| Динамическое добавление | Нужно вызывать updateTabbableNodes() |
Поддерживать актуальный список tabbable элементов |
Эта логика позволяет управлять фокусом внутри интерактивных контейнеров корректно, предотвращая ошибки клавиатурной навигации и обеспечивая предсказуемое поведение для пользователей, использующих Tab и другие средства навигации.