- mobile-patterns.md: Mobile layout & pattern systems (18.5KB) Fluid typography, container queries, safe-area, CSS architecture, touch-optimized components, iOS/Android specifics, testing checklist - mobile-layout-patterns.md: Mobile layout systems (11.5KB) CSS grid, single-column stack, full-bleed hero, card stack, swipeable carousel, split-screen, off-canvas nav, bottom sheet, FAB, component patterns - mobile-navigation-patterns.md: Mobile navigation (9.8KB) Bottom tab bar, top nav, hamburger menu, bottom sheet nav, pill nav, comparison matrix, navigation rules, swipe navigation, breadcrumbs, tab content - mobile-form-patterns.md: Mobile form patterns (10.3KB) Input types, keyboards, floating labels, validation patterns, progressive disclosure, autocomplete, masked inputs, toggle/radio, form anti-patterns - mobile-interaction-patterns.md: Touch & gestures (16.7KB) Swipe detection, long press, pull-to-refresh, touch feedback, scroll-reveal, parallax, sticky scroll, CSS scroll animations, touch carousel, haptic feedback, passive listeners - mobile-performance-patterns.md: Performance optimization (12.3KB) Core Web Vitals (LCP/INP/CLS), LCP optimization, INP debugging, CLS prevention, image optimization, lazy loading, service workers, CSS/JS optimization, network optimization - mobile-landing-patterns.md: Landing page patterns (21.3KB) Section sequencing, hero, social proof, feature cards, CTA patterns (inline/sticky/full-bleed), testimonials, pricing, FAQ accordion, footer, mobile checklist
423 lines
10 KiB
Markdown
423 lines
10 KiB
Markdown
---
|
||
title: Mobile Form Patterns
|
||
created: 2026-07-03
|
||
updated: 2026-07-03
|
||
type: system
|
||
tags: [mobile, forms, input, validation, UX, conversion]
|
||
sources:
|
||
- https://www.formCreatorai.com/mobile-form-design-patterns-maximize-completion
|
||
- https://subux.pro/guides/article/input-field-types-and-usage
|
||
- https://askusers.org/en/blog/mobile-form-optimization-completion-rates
|
||
- https://www.getworkform.com/blog/mobile-form-design-tips
|
||
- https://tinyform.com/post/mobile-form-statistics-ux-trends
|
||
- https://www.reform.app/blog/10-mobile-form-design-tips-for-better-ux
|
||
confidence: high
|
||
---
|
||
|
||
# Mobile Form Patterns — Формы и инпуты для мобильных
|
||
|
||
## 1. Mobile Form Statistics
|
||
|
||
- **63%** мобильных форм бросают на полпути (мобильная форма для завершения)
|
||
- Оптимизированные формы увеличивают completion rate до **43%**
|
||
- Мобильные формы имеют более высокий abandonment rate, чем десктоп
|
||
- Каждый дополнительный field = 10% снижение completion rate
|
||
|
||
## 2. Input Types & Keyboards
|
||
|
||
### 2.1 Correct Input Types
|
||
|
||
```html
|
||
<!-- Email — shows @ and . on keyboard -->
|
||
<input type="email" placeholder="you@example.com">
|
||
|
||
<!-- Phone — shows numeric keypad -->
|
||
<input type="tel" placeholder="+7 (___) ___-__-__">
|
||
|
||
<!-- Number — shows numeric keypad with minus -->
|
||
<input type="number" placeholder="100">
|
||
|
||
<!-- URL — shows .com and / on keyboard -->
|
||
<input type="url" placeholder="https://example.com">
|
||
|
||
<!-- Text — default, full keyboard -->
|
||
<input type="text" placeholder="Иван">
|
||
|
||
<!-- Search — shows search button on keyboard -->
|
||
<input type="search" placeholder="Поиск...">
|
||
|
||
<!-- Password — hides characters -->
|
||
<input type="password" placeholder="Пароль">
|
||
```
|
||
|
||
### 2.2 inputmode for Custom Keyboards
|
||
|
||
```html
|
||
<!-- Numeric keyboard without changing type -->
|
||
<input inputmode="numeric" pattern="[0-9]*" placeholder="1234">
|
||
|
||
<!-- Decimal keyboard -->
|
||
<input inputmode="decimal" placeholder="123.45">
|
||
|
||
<!-- Search keyboard -->
|
||
<input inputmode="search" placeholder="Искать...">
|
||
|
||
<!-- Tel keyboard -->
|
||
<input inputmode="tel" placeholder="+7 999 123-45-67">
|
||
|
||
<!-- Email keyboard -->
|
||
<input inputmode="email" placeholder="you@example.com">
|
||
```
|
||
|
||
### 2.3 Keyboard Hints
|
||
|
||
```html
|
||
<!-- Enter key label -->
|
||
<input type="text" placeholder="Сообщение" enterkeyhint="send">
|
||
|
||
<!-- Search button -->
|
||
<input type="search" placeholder="Поиск" enterkeyhint="search">
|
||
|
||
<!-- Next (for multi-field forms) -->
|
||
<input type="text" placeholder="Имя" enterkeyhint="next">
|
||
<input type="text" placeholder="Email" enterkeyhint="next">
|
||
<input type="text" placeholder="Телефон" enterkeyhint="done">
|
||
```
|
||
|
||
## 3. Form Layout Patterns
|
||
|
||
### 3.1 Single-Column Form
|
||
|
||
```css
|
||
.mobile-form {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20px;
|
||
padding: 20px 16px;
|
||
}
|
||
|
||
.form-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
```
|
||
|
||
### 3.2 Floating Label Pattern
|
||
|
||
```css
|
||
.form-group {
|
||
position: relative;
|
||
}
|
||
|
||
.form-input {
|
||
min-height: 48px;
|
||
padding: 16px 12px 8px;
|
||
border: 1px solid var(--border-1);
|
||
border-radius: 8px;
|
||
background: var(--surface-1);
|
||
font-size: 16px; /* Prevents iOS zoom */
|
||
width: 100%;
|
||
transition: border-color 0.15s, box-shadow 0.15s;
|
||
}
|
||
|
||
.form-input:focus {
|
||
border-color: var(--primary);
|
||
outline: none;
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent);
|
||
}
|
||
|
||
.form-label {
|
||
position: absolute;
|
||
left: 12px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
color: var(--text-secondary);
|
||
pointer-events: none;
|
||
transition: all 0.15s ease;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.form-input:focus ~ .form-label,
|
||
.form-input:not(:placeholder-shown) ~ .form-label {
|
||
top: 8px;
|
||
font-size: 12px;
|
||
color: var(--primary);
|
||
}
|
||
```
|
||
|
||
### 3.3 Multi-Field Row (When Appropriate)
|
||
|
||
```css
|
||
.form-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 12px;
|
||
}
|
||
|
||
.form-row-3 {
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
}
|
||
```
|
||
|
||
**Правила:**
|
||
- Только для связанных полей (имя/отчество, город/индекс)
|
||
- Всегда single-column на экранах < 360px
|
||
- Never for unrelated fields
|
||
|
||
## 4. Validation Patterns
|
||
|
||
### 4.1 Real-Time Validation
|
||
|
||
```css
|
||
.form-input.valid {
|
||
border-color: #22c55e;
|
||
}
|
||
|
||
.form-input.invalid {
|
||
border-color: #ef4444;
|
||
animation: shake 0.3s ease;
|
||
}
|
||
|
||
.form-error {
|
||
font-size: 12px;
|
||
color: #ef4444;
|
||
margin-top: 4px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.form-success {
|
||
font-size: 12px;
|
||
color: #22c55e;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
@keyframes shake {
|
||
0%, 100% { transform: translateX(0); }
|
||
25% { transform: translateX(-4px); }
|
||
75% { transform: translateX(4px); }
|
||
}
|
||
```
|
||
|
||
### 4.2 Inline Validation on Blur
|
||
|
||
```javascript
|
||
// Validate on blur, not on every keystroke
|
||
input.addEventListener('blur', () => {
|
||
const value = input.value;
|
||
if (!validate(value)) {
|
||
input.classList.add('invalid');
|
||
showError(input, getMessage(value));
|
||
} else {
|
||
input.classList.remove('invalid');
|
||
input.classList.add('valid');
|
||
showSuccess(input);
|
||
}
|
||
});
|
||
```
|
||
|
||
### 4.3 Validation Error Summary
|
||
|
||
```html
|
||
<!-- Show at top of form -->
|
||
<div class="form-error-summary" role="alert">
|
||
<p>Исправьте следующие ошибки:</p>
|
||
<ul>
|
||
<li><a href="#email">Введите корректный email</a></li>
|
||
<li><a href="#phone">Номер телефона должен содержать 10 цифр</a></li>
|
||
</ul>
|
||
</div>
|
||
```
|
||
|
||
## 5. Form UX Patterns
|
||
|
||
### 5.1 Progressive Disclosure (Step by Step)
|
||
|
||
```css
|
||
.form-step {
|
||
display: none;
|
||
}
|
||
|
||
.form-step.active {
|
||
display: block;
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; transform: translateY(10px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
.form-progress {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 16px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.form-progress__step {
|
||
flex: 1;
|
||
height: 4px;
|
||
background: var(--surface-2);
|
||
margin: 0 4px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.form-progress__step.active {
|
||
background: var(--primary);
|
||
}
|
||
```
|
||
|
||
### 5.2 Autocomplete & Autofill
|
||
|
||
```html
|
||
<input type="text" name="fname" autocomplete="given-name">
|
||
<input type="text" name="lname" autocomplete="family-name">
|
||
<input type="email" name="email" autocomplete="email">
|
||
<input type="tel" name="phone" autocomplete="tel">
|
||
<input type="text" name="city" autocomplete="address-level2">
|
||
<input type="text" name="postal" autocomplete="postal-code">
|
||
```
|
||
|
||
### 5.3 Masked Inputs
|
||
|
||
```javascript
|
||
// Phone mask
|
||
function formatPhone(value) {
|
||
const cleaned = value.replace(/\D/g, '');
|
||
const match = cleaned.match(/^(\d)(\d{0,3})(\d{0,3})(\d{0,2})(\d{0,2})$/);
|
||
if (match) {
|
||
return '+7' + (match[2] ? ' (' + match[2] : '') +
|
||
(match[3] ? ') ' + match[3] : '') +
|
||
(match[4] ? '-' + match[4] : '') +
|
||
(match[5] ? '-' + match[5] : '');
|
||
}
|
||
return value;
|
||
}
|
||
```
|
||
|
||
## 6. Form Component Patterns
|
||
|
||
### 6.1 Select/Picker
|
||
|
||
```html
|
||
<!-- Use native select for mobile — triggers OS picker -->
|
||
<select name="country">
|
||
<option value="">Выберите страну</option>
|
||
<option value="ru">Россия</option>
|
||
<option value="by">Беларусь</option>
|
||
</select>
|
||
|
||
<!-- Custom picker for mobile -->
|
||
<div class="picker-trigger">
|
||
<span class="picker-label">Выберите дату</span>
|
||
<span class="picker-arrow">▼</span>
|
||
</div>
|
||
<div class="picker-overlay">
|
||
<div class="picker-wheel">
|
||
<div class="picker-scroll">
|
||
<!-- OS-style scroll wheel -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
### 6.2 Checkbox & Radio
|
||
|
||
```css
|
||
/* Large touch targets */
|
||
.form-checkbox,
|
||
.form-radio {
|
||
width: 44px;
|
||
height: 44px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 2px solid var(--border-1);
|
||
border-radius: 8px;
|
||
margin-right: 12px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.form-checkbox::after,
|
||
.form-radio::after {
|
||
content: '';
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 4px;
|
||
background: var(--primary);
|
||
opacity: 0;
|
||
transition: opacity 0.2s;
|
||
}
|
||
|
||
.form-checkbox.checked::after,
|
||
.form-radio.checked::after {
|
||
opacity: 1;
|
||
}
|
||
```
|
||
|
||
### 6.3 Toggle Switch
|
||
|
||
```css
|
||
.toggle {
|
||
position: relative;
|
||
width: 52px;
|
||
height: 32px;
|
||
border-radius: 16px;
|
||
background: var(--surface-2);
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.toggle::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 2px;
|
||
left: 2px;
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 50%;
|
||
background: white;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.toggle.active {
|
||
background: var(--primary);
|
||
}
|
||
|
||
.toggle.active::after {
|
||
transform: translateX(20px);
|
||
}
|
||
```
|
||
|
||
## 7. Form Anti-Patterns
|
||
|
||
| ❌ Плохо | ✅ Хорошо |
|
||
|----------|-----------|
|
||
| Автофокус на первом поле | Автофокус только на 1 поле за шаг |
|
||
| Валидация при вводе | Валидация при blur или submit |
|
||
| Email type для всех текстовых полей | Правильный inputtype + inputmode |
|
||
| Фиксированная клавиатура | Динамическая клавиатура |
|
||
| 10+ полей в одну страницу | Прогрессивная подача (step-by-step) |
|
||
| Нет подсказок для форматов | Placeholder + подсказки |
|
||
| Только красная рамка при ошибке | Иконка + текст + анимация |
|
||
| Сложные пароли без указаний | Показ требований к паролю |
|
||
|
||
## 8. Mobile Form Checklist
|
||
|
||
| Category | Check |
|
||
|----------|-------|
|
||
| **Input Type** | Правильный type + inputmode |
|
||
| **Keyboard** | Правильная клавиатура для каждого поля |
|
||
| **Touch Targets** | Минимум 44×44px |
|
||
| **Labels** | Видимые labels (floating или above) |
|
||
| **Validation** | Inline, после blur, summary at top |
|
||
| **Autocomplete** | autocomplete attributes set |
|
||
| **Progress** | Step indicator для многостраничных |
|
||
| **Submit** | CTA всегда виден |
|
||
| **Feedback** | Success/error states |
|
||
| **Zoom** | 16px font-size на iOS |
|