Как исправить ошибку с отсутствием фокуса на инпуте
Что проверяют
Знаете ли вы, почему фокус вообще может не встать, и умеете ли искать причину, а не лечить всё через setTimeout. Часто это вопрос про React и доступность одновременно. Следом спрашивают, как поставить фокус при открытии модалки и вернуть его после закрытия.
Как отвечать
Сначала проверьте, где фокус на самом деле: document.activeElement в консоли, а в DevTools включите «Emulate a focused page», чтобы фокус не терялся при переходе в панель. Дальше по списку причин:
- элемента ещё нет в DOM:
focus()вызывают до монтирования. В React фокус ставят черезrefвuseEffectили атрибутомautoFocus; - элемент нельзя сфокусировать:
disabled,display: none,visibility: hidden, родитель с атрибутомinert. Скрытый элемент молча не принимает фокус, ошибки не будет; - фокус перехватывают: focus trap модального окна, чужой обработчик с
blur(),preventDefault()наmousedownу перекрывающего слоя. Перекрытие видно в DevTools или черезdocument.elementFromPoint(x, y); - инпут пересоздаётся: классическая ошибка React, когда фокус пропадает после каждого символа. Компонент объявлен внутри другого компонента или у инпута меняется
key, и React монтирует новый DOM-узел на каждом рендере; - мобильный Safari: программный
focus()вне жеста пользователя не открывает клавиатуру, вызывать его нужно прямо в обработчике нажатия.
Если под «нет фокуса» имеется в виду невидимая рамка, ищите outline: none в стилях и возвращайте индикатор через :focus-visible.
Где спотыкаются
Оборачивают focus() в setTimeout(..., 0) и считают вопрос закрытым. Иногда это срабатывает, но причина остаётся, и на медленном устройстве баг вернётся.
Убирают outline ради дизайна без замены. Пользователь клавиатуры перестаёт видеть, где находится, а это прямое нарушение доступности.
Не проверяют клавиатуру: мышью всё работает, а по Tab инпут пропускается из-за tabindex="-1" или неверного порядка элементов в DOM.