Проектирование UX-форм
1) Принципы
1. Сначала задача, потом поля. Формы — продолжение пользовательского сценария, а не список БД.
2. Один экран — одна цель. Уберите все, что не ведет к завершению задачи.
3. Никогда не теряйте данные. Автосейв, восстановление черновика, безопасные повторы.
4. Покажите «как правильно». Правила и примеры до ошибки; валидируйте бережно.
5. Доступность по умолчанию. Лейблы, фокус, контраст, клавиатурная навигация.
6. Предсказуемая скорость. Первый отклик ≤ 100 мс, отправка с явным статусом и прогрессом.
2) Информационная архитектура формы
Цель → шаги → поля. Начните с результата (например, «выплата средств») и выделите минимальный набор полей.
Группировка по смыслу: «Личные данные», «Оплата», «Подтверждение». Каждая группа ≤ 6 полей.
Прогрессивное раскрытие: дополнительные поля показывайте по условию (toggle/выбор страны).
Порядок полей — как в голове у пользователя: от известного к сложному.
3) Макет и сетка
Одна колонка для мобильных и большинства задач — быстрее по взгляду и таб-порядку.
Две колонки уместны для коротких взаимосвязанных полей (дата/время, имя/фамилия).
Высота строки 40–48 px, расстояние между полями 8–12 px (связанные) / 16–24 px (группы).
Выравнивание лейблов сверху поля; справа — для узких форм не использовать.
4) Лейблы, плейсхолдеры, хелперы
Лейбл обязателен. Плейсхолдер — пример, а не замена.
Helper-текст размещайте под полем: правила, формат, ссылка на пример.
Опциональные поля помечайте «(необязательно)» вместо «» на обязательных.
html
<label for = "iban"> IBAN <span class = "muted"> (optional) </span> </label>
<input id="iban" aria-describedby="iban-help">
<small id = "iban-help "> Format A-Z, 0-9; example: DE89 3704 0044 0532 0130 00 </small>
5) Шаги и прогресс
Многошаговые формы (KYC/выплаты): 3–5 шагов, явный прогресс «Шаг 2 из 4».
Сохраняйте завершенные шаги; разрешайте вернуться без потери данных.
Кнопки навигации: «Назад», «Далее», финальный «Подтвердить» — всегда на одном месте.
6) Управление вводом
Клавиатуры и атрибуты: `type`, `inputmode`, `autocomplete` под тип данных.
Маски ввода используйте мягко (телефон, IBAN, PAN, дата), храните нормализованные значения.
Автозаполнение не ломайте: корректные `autocomplete="given-name" | "cc-number" | "one-time-code"` и т. п.
Пресеты сумм/шорткаты: «+50 / +100 / Все» рядом с полем суммы.
7) Валидация и ошибки
Стратегия: до ввода (helper), во время (мягкие подсказки), после (на blur/submit).
Асинхронные проверки (уникальность логина, лимиты, риск) — с дебаунсом 250–400 мс.
Текст ошибок: причина → как исправить → альтернатива.
Summary-панель над формой для нескольких ошибок + фокус к первой ошибке.
Idempotency-Key для критичных действий (ставка/платеж) и безопасные ретраи.
8) Кнопки и отправка
Первичная CTA выделена цветом/размером, доступна по Enter.
`Busy`-состояние и блокировка повтора клика; при задержке > 3–5 с — «Ожидаем подтверждение…».
После успеха — явный статус (тост/экран «Готово») + что будет дальше.
9) Доступность (A11y)
Правильные связи `label → input`, ошибки через `aria-describedby`, критичные — `role="alert"`.
Видимое `:focus-visible`, порядок Tab соответствует визуальному.
Контраст текста/иконок ≥ AA; смысл не только цветом.
Поддержка `prefers-reduced-motion`: минимум анимаций.
Для групп радиокнопок — `fieldset/legend`, для подсказок — `role="status"`.
10) Локализация и международные форматы
Даты/валюты/номера — локальные при вводе, хранилище — ISO/минорные единицы.
Допускайте разные алфавиты в именах/адресах; не ограничивайте дефисы/апострофы.
Телефон храните в E.164; страна выбирается явно или из `+CC` при вставке.
11) Перформанс и стабильность
Первый визуальный отклик ≤ 100 мс; асинхронные проверки — не блокируют экран.
Skeleton вместо «висящего» спиннера, фиксируйте высоты, избегайте CLS.
Виртуализируйте длинные списки (например, страны/банки).
Анимируйте только `transform/opacity`, без массовых blur/теней.
12) Безопасность и приватность
Не логируйте PAN/CVC/паспорт; не отправляйте в RUM/консоль.
Маскируйте чувствительные поля, не сохраняйте их в автосейв.
Не раскрывайте, существует ли аккаунт: «Если email зарегистрирован, мы отправим письмо».
Хранение — минимально необходимое; показывайте, зачем требуется KYC.
13) Паттерны по типовым сценариям
13.1 Платеж/депозит
Поле суммы с пресетами, валюта явно указана.
PAN с мягкой маской, Luhn-проверкой; CVC скрыт; дата `MM/YY` с авто-`/`.
Текст о комиссиях/сроках рядом, не в tooltip.
13.2 Вывод средств
Шаги: «Сумма → Метод → Подтверждение».
Прогресс и «Обычно до N минут/часов» (без жестких обещаний).
Варианты метода по стране; предупреждения о лимитах.
13.3 KYC
Пошаговый загрузчик файлов: требования к формату/весу, предпросмотр, приватность.
Сроки проверки и канал статусов (почта/уведомление).
13.4 Лимиты и ответственная игра
Понятные единицы (в день/неделю/месяц), преднастройки, подтверждение изменений, «Вступит в силу через…».
14) Антипаттерны
Placeholder вместо лейбла.
Ошибки «на каждый символ» без дебаунса.
Сброс формы при ошибке.
Критичная инструкция спрятана только в tooltip.
Жесткие маски, запрещающие валидные символы/вставку.
Блокировка всей страницы ради проверки одного поля.
Отправка без явного busy/прогресса.
15) Сниппеты реализации
Сводка ошибок + фокус к первой проблеме
js function focusFirstError() {
const el = document. querySelector('[aria-invalid="true"]');
if (el) el. focus({ preventScroll:false });
}
Кнопка с мгновенным busy и идемпотентностью
js btn. addEventListener('click', async () => {
btn. classList. add('is-busy');
try {
const r = await fetch('/api/submit', {
method: 'POST',
headers: { 'Idempotency-Key': crypto. randomUUID() },
body: new FormData(document. querySelector('form'))
});
if (!r.ok) throw new Error();
// success UI
} catch {
// show retry
} finally {
btn. classList. remove('is-busy');
}
});
HTML-каркас доступной группы радиокнопок
html
<fieldset>
<legend> How to get </legend>
<label><input type="radio" name="method" value="sepa"> SEPA</label>
<label><input type="radio" name="method" value="swift"> SWIFT</label>
</fieldset>
16) Токены дизайн-системы (пример)
json
{
"form": {
"gap": 12,
"groupGap": 20,
"labelSize": 14,
"fieldHeight": 44,
"radius": 10
},
"motion": {
"pressMs": 90,
"hoverMs": 160,
"overlayInMs": 240
},
"validation": {
"debounceMs": 300,
"blurFeedbackMs": 100
},
"a11y": {
"focusRing": { "width": 2, "offset": 2 },
"contrastAA": true
}
}
CSS-пресеты
css
.form { display:grid; gap:12px; }
.form__group { display:grid; gap:20px; }
label { font-size:14px; }
.input { height:44px; padding:0 12px; border-radius:10px; }
.input:focus-visible { outline:2px solid var(--focus-ring); outline-offset:2px; }
.field-error { color: var(--role-danger); font-size:.875rem; margin-top:6px; }
17) Метрики и эксперименты
Completion Rate, Time-to-Complete, Error Rate по полям.
Retry Success Rate, доля брошенных форм, глубина шага.
CTR подсказок/примеров, доля автозаполнений.
A/B: порядок полей, пресеты сумм, тексты ошибок, разделение на шаги.
18) QA-чек-лист
Смысл и поток
- Поля соответствуют цели; нет лишних.
- Группы логичны; максимум 6 полей на группу.
Ввод
- Корректные `type/inputmode/autocomplete`.
- Маски мягкие, вставка не ломается, caret предсказуем.
Валидация
- Helper до ввода; ошибки на blur/submit; дебаунс 250–400 мс.
- Summary-панель для множественных ошибок; фокус к первой.
Доступность
- Лейблы связаны; контраст ≥ AA; `:focus-visible` виден.
- Навигация с клавиатуры; радиогруппы с `fieldset/legend`.
Перформанс
- Первый отклик ≤ 100 мс; нет «висящих» спиннеров.
- Нет CLS; длинные списки виртуализированы.
Безопасность
- Нет логов чувствительных полей; PAN/CVC не в автосейве.
- Идемпотентность и безопасные ретраи включены.
19) Специфика iGaming
Ставки: поле суммы + пресеты, мгновенный `busy`, оптимистичное подтверждение с возможностью undo (если регламент допускает).
Платежи/выводы: явные комиссии и сроки рядом с полями, не только в подсказках; проверка лимитов и статуса KYC.
Турниры: форма регистрации с минимальным набором данных, правила и соглашаемые чекбоксы без «темных паттернов».
Ответственная игра: формы установки лимитов с понятными интервалами и превью результата («Ваш дневной лимит станет 2 000 ₴ с завтрашнего дня»).
Краткое резюме
Хорошая форма — это ясная цель, минимальный набор полей, понятные правила до ошибки, мгновенный отклик и сохраненные данные. Проектируйте структуру от сценария, уважайте доступность и локали, включайте безопасные ретраи и идемпотентность. Так формы ощущаются быстрыми и доверенными — особенно в критичных сценариях iGaming.