Skip to main content
Назад к блогу
5 мин чтения

Баг, который проявился только на iPhone SE

Чекаут, который работал на каждом устройстве, кроме 4-дюймового экрана. Как тач-таргет 44px, фиксированный футер и адресная строка Safari сложились в баг, который никто не мог воспроизвести в офисе.

performanceuxcase-study

Тикетинг-платформа E7 была в продакшне два месяца. Конверсия чекаута: 78% по всем мобильным устройствам. Хорошо, не отлично, но в рамках индустриальных бенчмарков.

Потом я сегментировал по устройствам. iPhone 13/14/15: 81%. Pixel серия: 79%. Samsung Galaxy S серия: 77%. iPhone SE (2-е и 3-е поколение): 34%.

Тридцать четыре процента. Половина конверсии каждого другого устройства. На устройстве, которое носили 12% наших мобильных пользователей.

Поиск

Данные говорили что, но не где. Воронка чекаута имела 4 шага: выбор мест → обзор корзины → данные оплаты → подтверждение. Мне нужно было понять, на каком шаге утекают.

Разбивка воронки для iPhone SE:

ШагОтсев (iPhone SE)Отсев (все мобильные)
Выбор мест → Обзор корзины8%6%
Обзор корзины → Данные оплаты14%5%
Данные оплаты → Подтверждение44%11%
Общий отказ66%22%

Катастрофа была на шаге 3 → 4. 44% пользователей iPhone SE, дошедших до формы оплаты, никогда не завершали платёж. На каждом другом устройстве — 11%.

Воспроизведение

Взял тестовый iPhone SE (3-е поколение, 4.7-дюймовый экран, iOS 17). Открыл чекаут. Выбрал места. Просмотрел корзину. Нажал «Перейти к оплате».

Форма оплаты загрузилась. Stripe Elements отрендерил поля карты. Всё выглядело нормально.

Потом попробовал нажать «Оплатить €45.00».

Кнопка была видна. Но когда я тапнул — ничего. Тапнул снова. Ничего. Прокрутил вниз — кнопка ушла вверх. Прокрутил вверх — кнопка ушла вниз. Она убегала от пальца.

Потом заметил: адресная строка Safari была в развёрнутом состоянии. На 4.7-дюймовом экране это крадёт около 50px высоты вьюпорта. Кнопка оплаты была в position: fixed футере, позиционированном на bottom: 0 — но развёрнутая адресная строка Safari сдвинула визуальный вьюпорт вверх, и кнопка рендерилась за нижней панелью инструментов Safari.

Пирамида из трёх багов

Это был не один баг. Их было три, наложенных друг на друга:

Баг 1: Фиксированный футер и динамический вьюпорт Safari

Кнопка оплаты жила в фиксированном футере:

.checkout-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 16px;
}

На больших экранах это работает. На iPhone SE с развёрнутой адресной строкой Safari bottom: 0 означает «низ layout viewport» — который находится за панелью инструментов Safari. Кнопка рендерится, но нетапабельна, потому что UI браузера её закрывает.

Фикс: Заменить bottom: 0 на bottom: env(safe-area-inset-bottom) и переключиться с 100vh на 100dvh (dynamic viewport height) для контейнера страницы. dvh учитывает динамическую панель Safari.

.checkout-footer {
  position: fixed;
  bottom: env(safe-area-inset-bottom, 0px);
  left: 0;
  right: 0;
  padding: 16px;
}

.checkout-page {
  min-height: 100dvh;
}

Баг 2: Тач-таргет был слишком маленьким

Даже после фикса вьюпорта кнопку было трудно тапнуть на 4-дюймовом экране. Кнопка «Оплатить» была 36px высотой — ниже рекомендуемого Apple минимума в 44px для тач-таргетов. На 14 Pro 36px нормально, потому что экран большой. На SE каждый пиксель тач-таргета критичен.

Фикс: Увеличил высоту кнопки до 48px и добавил min-height: 44px ко всем интерактивным элементам в чекауте.

Баг 3: Stripe Elements рендерились за экраном

Поля ввода карты Stripe (номер карты, срок действия, CVC) — это iframe. На маленьком экране три поля были стопкой вертикально, толкая общую высоту формы за пределы вьюпорта. Пользователю нужно было скроллить, чтобы увидеть поле CVC, но фиксированный футер закрывал низ скроллируемой области, и поле CVC было частично скрыто за кнопкой «Оплатить».

Пользователи вводили номер карты и срок действия, потом не могли увидеть поле CVC, потом не могли найти кнопку отправки, потом уходили.

Фикс: Изменил лейаут Stripe Elements со стопки на инлайн (номер карты в одну строку, срок действия + CVC во вторую). Это уменьшило высоту формы достаточно, чтобы всё помещалось во вьюпорт на 4.7-дюймовом экране без скролла за фиксированный футер.

Почему никто не поймал

  1. Ни у кого в офисе не было iPhone SE. Наши тестовые устройства — iPhone 14, Pixel 7, Samsung A54. Все с большими экранами. SE — 4.7 дюйма, значительно меньше современных телефонов.

  2. Safari DevTools не симулирует динамическую панель. Когда используешь Safari responsive design mode на Mac, он рендерит страницу в правильных размерах экрана, но не симулирует разворачивающуюся/сворачивающуюся адресную строку. Баг невидим в симуляторе.

  3. Отсев выглядел как поведение пользователя, а не баг. 34% конверсия выглядит как «эти пользователи не готовы покупать», а не «эти пользователи физически не могут тапнуть кнопку». Без сегментации по устройствам в аналитике это было бы невидимым.

Фикс в продакшне

Три изменения, задеплоенные в одном PR:

  1. 100vh100dvh на контейнере страницы чекаута
  2. bottom: 0bottom: env(safe-area-inset-bottom) на фиксированном футере
  3. Лейаут Stripe Elements со стопки на инлайн на экранах уже 430px
  4. Все тач-таргеты в чекауте установлены на min-height: 44px

Конверсия чекаута на iPhone SE выросла с 34% до 76% за первую неделю. Всё ещё ниже 81% на больших iPhone — маленькие экраны всегда будут иметь чуть ниже конверсию — но отсев 44% → 11% на шаге оплаты сравнялся с каждым другим устройством.

Что я проверяю теперь

Этот баг изменил мой пре-лаунч QA-чеклист. Для каждого чекаута или формы я теперь тестирую:

  1. iPhone SE (4.7 дюйма) с развёрнутой адресной строкой Safari. Не симулятор — реальное устройство с реальным пальцем.
  2. dvh вместо vh для любого полноэкранного лейаута на мобилке. Динамическая панель Safari делает 100vh ненадёжным.
  3. env(safe-area-inset-bottom) на каждом элементе с position: fixed. И вырезы, и панель Safari съедают пространство снизу.
  4. Тач-таргеты минимум 44px. Не 36px, не 40px. 44px. HIG Apple существует неспроста.
  5. Лейаут Stripe Elements на узких экранах. Стопочный лейаут — дефолт, и он ломается на маленьких вьюпортах. Всегда тестируй на самом узком поддерживаемом устройстве.

У iPhone SE 12% доля среди наших мобильных пользователей. Это не ниша — это тысячи людей в месяц, которые не могли купить билеты, потому что кнопка была на 8px слишком маленькой и на 50px слишком низкой.


Если в данных конверсии видно устройственно-специфичный отсев и ты не понимаешь почему — давай разберёмся вместе. Иногда это одно CSS-свойство.