feat(mobile): comprehensive mobile web design patterns — 6 new articles
- 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
This commit is contained in:
1 parent
76c4c5b4fe
commit
083f6ba783
7 files changed
+4192
No files matched your search
@@ -0,0 +1,422 @@
|
||||
---
|
||||
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 |
|
||||
Reference in new issue
Block a user