Мёртвые кнопки и клики в никуда: как найти контролы, которые ничего не делают
Почему скриншот не видит сломанный onClick, что считать исходом клика и как отдать разработчику баг с селектором
Алексей Смирнов
Lead Product Architect, UXCheck
На скриншоте все кнопки одинаково живые. Синий фон, скругления, тень при наведении: визуально всё сделано. Но за «Получить консультацию» может стоять href="#", за «В корзину» обработчик, который упал с ошибкой в консоли, за «Открыть чат» виджет, который не смонтировался из-за блокировщика рекламы. Пользователь нажимает, ничего не происходит, он нажимает ещё раз и уходит.
Это самая частая и самая невидимая категория дефектов в интерфейсах, собранных с помощью нейросетей. Генератор рисует компонент, а логику откладывает в TODO, который никто не открыл. В обзоре слепых зон вайбкодинга это было одним пунктом; здесь отдельная методика поиска.
Таксономия мёртвых контролов
- Пустая ссылка.href="#" или href="javascript:void(0)" без обработчика. Клик прокручивает страницу вверх или не делает ничего.
- Кнопка без обработчика.<button> внутри формы без action, или onClick, который остался заглушкой console.log.
- Обработчик с ошибкой.Клик вызывает исключение: undefined is not a function, обращение к незагруженному SDK, CORS на запросе. Пользователь видит тишину, разработчик красную строку в консоли, которую никто не смотрит.
- Несмонтированный виджет.Чат, калькулятор, форма записи из стороннего сервиса не загрузились: домен заблокирован, ключ протух, скрипт упал на другом виджете.
- Модалка за модалкой.Окно открылось, но под другим окном или с z-index ниже фиксированной шапки. Технически «работает», для человека нет.
- Клик в никуда на мобильных.Элемент перекрыт невидимым слоем, ловит тап только по краю или уезжает под клавиатуру. Об этом отдельно в статье о тач-интерфейсах.
Что считать исходом клика
Чтобы находка была проверяемой, у клика должен быть измеримый исход. Их всего четыре: сменился URL, появилось окно или новая область на странице, изменилось состояние (товар в корзине, счётчик, подсветка), ничего не изменилось. Первые три означают успех разной степени, после четвёртого контрол становится кандидатом в мёртвые.
Кандидат, а не приговор: сеть могла моргнуть, обработчик мог ждать данные. Поэтому работает правило двух кликов: контрол, который дважды на одном адресе не открыл ни страницу, ни окно, признаётся мёртвым и больше не предлагается для прохода к цели. Время до исхода измеряется отдельно, между нажатием и сменой URL или появлением окна, без учёта пауз самого аудита. Медленный, но живой контрол — это уже вопрос производительности.
Модель выбирает один контрол из уже снятого списка, Playwright кликает. Кнопка, дважды не открывшая ни страницу, ни окно, исключается из дальнейших предложений на этом адресе. Исход клика и его время пишутся в отчёт. Оплата, СМС и капча останавливают проход: реальные заказы аудит не создаёт.
Почему это не находит ни один линтер
Статический анализ видит код, а не поведение. Он не знает, что виджет чата заблокирован у 30% посетителей с AdBlock, что API-ключ Яндекс Карт истёк вчера, а модалка рендерится под шапкой только при ширине 375 px. Юнит-тесты проверяют функцию, а не путь пользователя. Единственный способ найти мёртвый контрол: нажать на него в браузере, как это делает человек.
При этом нажимать нужно бережно. Аудит чужого продакшена — это один пользователь, один браузер, паузы между действиями, остановка перед оплатой. Полный краулер всех кликабельных элементов на 3000 страницах — это уже нагрузочное тестирование, а не аудит.
Мёртвые контролы как регрессия
Кнопка редко рождается мёртвой. Чаще она умирает: обновили библиотеку компонентов, переименовали API-метод, сменили домен виджета, перенесли форму на другой сервис и забыли одну страницу. Ни один из этих релизов не имел цели сломать кнопку, поэтому никто её не проверил.
Именно поэтому проверку кликов нужно повторять: сегодня контрол живой, через неделю нет. Как устроен еженедельный контроль и почему исправленное не должно шуметь в новом отчёте, разобрано в статье о недельной дельте.
Формат находки, которую можно вставить в Cursor
Отчёт о мёртвой кнопке полезен, если разработчик или AI-редактор может по нему воспроизвести и исправить дефект без уточнений. Минимальный набор:
Страница: https://example.ru/uslugi/remont
Элемент: button.hero__cta[data-action="consult"]
Текст: «Получить консультацию»
Действие: клик ×2 (desktop 1440, mobile 390)
Ожидание: открытие формы или переход на /contacts
Факт: URL не изменился, окон нет, в консоли:
TypeError: window.ym is not a function
Серьёзность: high (главный CTA первого экрана)
Как проверить исправление: клик открывает форму ≤ 1 сТри правила приоритизации
- 1Место важнее количества.Одна мёртвая кнопка главного CTA важнее десяти сломанных ссылок в подвале. Серьёзность определяется позицией на пути к цели.
- 2Общее считается один раз.Неработающий чат в шапке на 40 страницах — это одна находка со списком адресов, а не 40.
- 3Ошибка консоли: улика, а не находка.Красная строка сама по себе ничего не значит для пользователя. Она становится находкой, когда связана с исходом клика: нажал, ничего не произошло, вот ошибка.
Частые вопросы
- Как быстро найти неработающие кнопки на сайте?
- Пройти путь к целевому действию в браузере с открытой консолью, нажимая каждый контрол на пути дважды. Если после двух кликов не изменился URL, не появилось окно и не изменилось состояние, контрол мёртв. Автоматизировать это можно через Playwright.
- Почему кнопка работает у разработчика и не работает у клиентов?
- Типичные причины: сторонний виджет заблокирован расширением, истёк API-ключ, обработчик зависит от скрипта, который не загрузился на медленной сети, или элемент перекрыт другим слоем только на конкретной ширине экрана.
- Считается ли медленная кнопка мёртвой?
- Нет. Если клик в итоге открывает страницу или окно, контрол живой, а задержка — это находка о производительности. Мёртвым считается контрол, который дважды не дал никакого исхода.
Источники, исследования и стандарты
- [1]Nielsen Norman Group (NN/g): Visibility of System Status; Feedback Latency and Perceived Responsiveness
- [2]Baymard Institute: Product Page UX: неработающие и неочевидные элементы карточки товара
- [3]Microsoft Playwright: Auto-waiting, actionability checks и трассировка действий в браузере
- [4]Addy Osmani (Chrome Engineering): Vibe Coding is not an excuse for low-quality work
Хотите узнать, есть ли эти ошибки на вашем сайте?
UXCheck проходит сайт в живом браузере глазами вашей аудитории, находит скрытые баги верстки, трение в формах и чекауте и формирует список селекторов для исправления.
1 бесплатный аудит на аккаунт
Читайте также по теме
Все статьиОшибки вайбкодинга: 5 слепых зон интерфейса, созданного нейросетями
Вайбкодинг ускорил прототипирование в 10 раз, но породил невидимый UX-долг. Исследования Addy Osmani и Nielsen Norman Group: где нейросети ломают логику пользователей и как это исправить.
Скорость сайта и конверсия: TTFB, отрисовка первого экрана и задержка клика
Каждые 100 мс задержки стоят до 1% конверсии. Разбираем метрики, которые реально связаны с деньгами: TTFB, LCP, время реакции на клик и заполнение формы, и почему лабораторный балл Lighthouse не заменяет измерения на пути к цели.
Регрессионный UX: почему ваш интерфейс незаметно деградирует от релиза к релизу
Программисты тестируют код unit-тестами, но кто тестирует сценарии пользователя? Разбираем проблему тихих UX-регрессий в продуктовых командах и методику еженедельного контроля.