Библиотека Focus-trap предназначена для управления фокусом внутри модальных окон, всплывающих панелей и других интерактивных областей. Основная цель — ограничить навигацию клавишей Tab так, чтобы пользователь оставался внутри выбранного контейнера. Несмотря на универсальность решения, при работе в iOS Safari возникают специфические проблемы, связанные с особенностями мобильной платформы и поведения фокуса в браузере.
Отсутствие стандартного Tab-фокуса На мобильных
устройствах клавиатура не содержит клавиш Tab, поэтому привычный цикл
фокусировки через Tab не работает. Focus-trap по умолчанию полагается на
событие keydown для клавиши Tab, что делает часть его
логики неэффективной на iOS. Это особенно заметно при использовании
внешних клавиатур, где поведение может отличаться от настольного
Safari.
Всплывающая клавиатура и смещение элементов При
появлении виртуальной клавиатуры Safari изменяет размеры окна
(window.innerHeight) и может автоматически прокручивать
страницу так, чтобы активное поле ввода было видимо. Это приводит к
неожиданным сдвигам контента внутри focus-trap контейнера, нарушая
визуальный порядок элементов и создавая ощущение “прыгающего”
интерфейса.
Фокус на скрытых элементах iOS Safari иногда
позволяет установить фокус на элементы, которые визуально скрыты или
перекрыты другими слоями. Библиотека Focus-trap использует
tabindex для управления доступностью элементов, однако
Safari может игнорировать этот атрибут в некоторых условиях, например,
если элемент имеет display: none или
opacity: 0. Это создаёт риск выхода фокуса за пределы
заданного контейнера.
Непредсказуемый первый фокус При инициализации
focus-trap на модальном окне первый элемент может не получать фокус
автоматически. Это связано с тем, что iOS Safari требует явного
пользовательского взаимодействия перед установкой фокуса
(focus()), иначе вызов игнорируется.
Проблемы с touch-событиями Клик или тап по
элементу внутри focus-trap может не приводить к ожидаемому срабатыванию
focus. В некоторых случаях приходится программно вызывать
focus() в обработчике touchstart или
click, чтобы корректно обновить состояние фокуса.
Сбой restoreFocus Focus-trap предоставляет опцию
returnFocusOnDeactivate, которая возвращает фокус на
элемент, который был активен до активации ловушки. На iOS Safari эта
функция работает нестабильно: если элемент исходного фокуса находится за
пределами видимой области или скрыт при деактивации trap, фокус может
потеряться или установиться на body.
Использование initialFocus Задание
явного элемента через параметр initialFocus позволяет
избежать проблем с первым фокусом. На iOS Safari лучше выбирать
интерактивный элемент, который уже присутствует в DOM и видим на
экране.
focusTrap.createFocusTrap(modalElement, {
initialFocus: modalElement.querySelector('input[type="text"]'),
escapeDeactivates: true,
clickOutsideDeactivates: true
});Обработка событий touch Для обеспечения
корректной работы фокуса при касаниях можно добавить обработку
touchstart с вызовом focus():
modalElement.addEventListener('touchstart', (event) => {
if (!event.target.matches('input, button, textarea')) return;
event.target.focus();
});Динамическая корректировка размеров При открытии
модального окна необходимо учитывать изменение высоты окна и прокрутку
контента. Использование window.visualViewport.height и
явная установка scrollTop для контейнера focus-trap
помогает избежать “прыжков”:
modalElement.style.maxHeight = `${window.visualViewport.height}px`;
modalElement.scrollTop = 0;Проверка видимости элементов Перед активацией focus-trap рекомендуется фильтровать элементы, которые фактически могут получать фокус:
const focusableElements = Array.from(modalElement.querySelectorAll('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])'))
.filter(el => el.offsetParent !== null && !el.disabled);focus(). Необходимо сочетать его с явными интерактивными
действиями пользователя.iOS Safari накладывает ряд специфических ограничений на управление
фокусом, что требует комбинированного подхода: настройка параметров
focus-trap (initialFocus,
returnFocusOnDeactivate), программная обработка
touch и корректировка размеров контейнеров. Учитывая эти
особенности, библиотека остаётся полезным инструментом для обеспечения
доступности, но требует дополнительной адаптации под мобильные
платформы.