Почему подсказка не показывается на телефоне — три причины и как починить

Симптом знакомый: на ноутбуке наводишь мышь на иконку с вопросом — подсказка всплывает, всё красиво. Открываешь на телефоне — тишина. Или хуже: подсказка выскочила от случайного тапа и висит, пока не ткнёшь в другое место.
Причина почти всегда одна из трёх. Идём от самой частой.
Причина 1. Подсказка висит на наведении, а у пальца наведения нет
Это девять случаев из десяти. Подсказка показывается через :hover, но у сенсорного экрана нет состояния «курсор над элементом» — есть только «касание было» и «касания нет».
Что при этом делают браузеры, документация MDN описывает честно: :hover на тачскрине может не сработать никогда, может сработать на мгновение после касания, а может остаться включённым, пока человек не коснётся другого элемента. Отсюда и оба симптома сразу — и «ничего не показывается», и «залипло».
Как проверить. Открой DevTools, включи режим мобильного устройства и отключи эмуляцию мыши — или просто возьми телефон и тапни по иконке дважды: если подсказка появляется только на второй тап или не исчезает после, ты в этом случае.
Как починить. Перестань считать наведение единственным способом открыть подсказку. Есть медиазапрос, который прямо спрашивает у устройства, умеет ли оно наводить, — и он давно поддерживается везде:
@media (hover: hover) and (pointer: fine) {
.hint:hover .tip { display: block; }
}
Для остальных устройств подсказка должна открываться по тапу или по фокусу — то есть быть настоящей кнопкой:
<button type="button" aria-describedby="tip-1">Что это?</button>
<span id="tip-1" role="tooltip" hidden>Номер карты — 16 цифр без пробелов</span>
Кнопка даёт бонусом клавиатуру: с Tab подсказка тоже откроется.
Причина 2. Это не подсказка, а атрибут title
Второй по частоте случай: в разметке стоит title="...", и на компьютере это работает как всплывающая подсказка. На телефоне — нет. Браузеры на сенсорных устройствах её просто не показывают.
Документация MDN формулирует жёстко: использование title крайне проблемно для людей с сенсорными устройствами, для тех, кто ходит с клавиатуры, для программ чтения с экрана и для людей с нарушениями моторики. То есть это не «баг на мобилке» — это атрибут, на который вообще нельзя закладывать важный смысл.
Как проверить. Поищи в коде title= на иконках и ссылках. Если текст подсказки живёт там — нашёл.
Как починить. Реши, насколько текст важен:
- Важен для действия (формат телефона, что входит в тариф) — не прячь вообще. Поставь обычной строкой под полем. Такая подсказка не исчезает и работает у всех — та же логика, что в разборе плейсхолдер или подпись поля.
- Приятное дополнение — вынеси в настоящий элемент с кнопкой-триггером, как в примере выше.
Причина 3. Подсказка есть, но её обрезает контейнер
Реже, но обиднее всего: элемент в DOM, стили применились, а на экране ничего. Виноват родитель с overflow: hidden (карточка, слайдер, модалка), низкий z-index или подсказка, уехавшая за правый край узкого экрана.
Как проверить. В DevTools выбери элемент подсказки и посмотри его размеры и координаты. Классический признак — ненулевой размер и позиция за пределами экрана либо видимая область в ноль пикселей. Если стили вообще не применились, это уже другая история — она разобрана в статье почему не работают стили CSS.
Как починить. Не воюй с overflow у родителя — вынеси подсказку из него. В современных браузерах для этого есть встроенный механизм:
<button popovertarget="tip-2">Что это?</button>
<div id="tip-2" popover>Спишем 1 490 ₽ сразу после подтверждения</div>
Элемент с атрибутом popover рисуется поверх всего и не зависит от overflow родителя.
Три правила, чтобы не возвращаться к этой проблеме
Стандарт доступности WCAG (критерий 1.4.13) требует от всплывающего контента ровно трёх вещей — их удобно держать как чек-лист:
- Закрываемость. Подсказку можно убрать, не убирая курсор и не меняя фокус, — например, по Esc.
- Наводимость. На курсор её можно перевести мышь, и она не исчезнет по дороге.
- Стабильность. Она держится, пока человек не уберёт триггер или не закроет её сам.
Третий пункт объясняет, почему «покажем подсказку на две секунды и спрячем» — плохая идея: люди читают с разной скоростью, и автоскрытие ломает как раз тех, кому подсказка нужнее всего.
Главный вывод простой: подсказка, без которой нельзя выполнить действие, не должна жить в наведении. Наведение — это бонус для мыши. Всё, что обязательно, пишется на экране обычным текстом — по правилам микрокопии. А если остальная вёрстка на телефоне тоже ведёт себя странно, начни с чек-листа адаптивности.
Почему я не поймал это в режиме мобильного устройства в браузере?
Потому что эмуляция мобильного в DevTools меняет размер экрана и user-agent, но мышь у тебя остаётся настоящая. Курсор по-прежнему наводится, :hover срабатывает, подсказка исправно всплывает — и баг остаётся невидимым до первого живого телефона. Именно поэтому такие вещи доезжают до продакшена: на машине разработчика они не воспроизводятся. Включи в DevTools эмуляцию сенсорного ввода или просто открой страницу с телефона — двух минут хватает.
Можно просто показывать подсказку по тапу?
Да, и это правильный путь — но триггер должен быть настоящей кнопкой, а не div с обработчиком. Иначе подсказка не откроется с клавиатуры и не будет объявлена программой чтения с экрана.
Почему подсказка залипает после тапа?
Это то самое поведение :hover на сенсорных экранах: состояние наведения остаётся на элементе до касания другого. Лечится тем же медиазапросом hover: hover — без него любой «ховер-эффект» на телефоне ведёт себя непредсказуемо.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





