Форма с валидацией
HTML-форма с JS-валидацией в реальном времени — проверка при submit и при
blurполя, показ ошибок рядом с полем.
Задача
Нужна форма регистрации/входа, которая проверяет поля при потере фокуса и при отправке, показывает понятные сообщения об ошибках и не отправляет данные с невалидными значениями.
Решение
<form class="form" id="signupForm" novalidate>
<div class="form__group">
<label class="form__label" for="email">Email</label>
<input class="form__input" type="email" id="email" name="email"
placeholder="you@example.com" autocomplete="email" />
<span class="form__error" id="emailError" aria-live="polite"></span>
</div>
<div class="form__group">
<label class="form__label" for="password">Пароль</label>
<input class="form__input" type="password" id="password" name="password"
placeholder="Минимум 8 символов" autocomplete="new-password" />
<span class="form__error" id="passwordError" aria-live="polite"></span>
</div>
<button class="form__submit" type="submit">Создать аккаунт</button>
</form>
.form { max-width: 400px; display: flex; flex-direction: column; gap: 20px; }
.form__group { display: flex; flex-direction: column; gap: 6px; }
.form__label { font-size: 0.875rem; font-weight: 500; color: #374151; }
.form__input {
padding: 10px 14px;
border: 1px solid #d1d5db;
border-radius: 8px;
font-size: 0.95rem;
transition: border-color 0.15s;
}
.form__input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.15); }
.form__input.invalid { border-color: #ef4444; }
.form__input.valid { border-color: #22c55e; }
.form__error { font-size: 0.8rem; color: #ef4444; min-height: 1.2em; }
.form__submit {
padding: 12px;
background: #3b82f6;
color: #fff;
border: none;
border-radius: 8px;
font-size: 1rem;
cursor: pointer;
}
.form__submit:hover { background: #2563eb; }
const form = document.getElementById('signupForm');
const rules = {
email: {
el: => document.getElementById('email'),
error: => document.getElementById('emailError'),
validate(value) {
if (!value) return 'Email обязателен';
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return 'Неверный формат email';
return '';
},
},
password: {
el: => document.getElementById('password'),
error: => document.getElementById('passwordError'),
validate(value) {
if (!value) return 'Пароль обязателен';
if (value.length < 8) return 'Минимум 8 символов';
return '';
},
},
};
function validateField(name) {
const { el, error, validate } = rules[name];
const input = el;
const msg = validate(input.value.trim());
const errEl = error;
errEl.textContent = msg;
input.classList.toggle('invalid', !!msg);
input.classList.toggle('valid', !msg && input.value.length > 0);
return !msg;
}
// Валидация при потере фокуса
Object.keys(rules).forEach((name) => {
rules[name].el.addEventListener('blur', () => validateField(name));
rules[name].el.addEventListener('input', () => {
if (rules[name].el.classList.contains('invalid')) validateField(name);
});
});
// Валидация при submit
form.addEventListener('submit', (e) => {
e.preventDefault();
const valid = Object.keys(rules).map(validateField).every(Boolean);
if (!valid) return;
console.log('Форма валидна, отправляем...');
// fetch('/api/signup', { method: 'POST', body: new FormData(form) });
});
Ключевые моменты
novalidateна форме — отключает браузерную валидацию, чтобы использовать кастомную.aria-live="polite"на.form__error— screen reader озвучит появление ошибки.- Валидация в
blur(не при вводе) — не мешать пользователю в процессе набора. - Повторная валидация при
inputтолько если поле уже помечено какinvalid— убрать ошибку как только исправили.
Варианты
- Нативная валидация без JS:
required,type="email",minlength,pattern— плохо стилизуется. - React Hook Form — лучший выбор для React-форм: минимум ре-рендеров, встроенная валидация.
- Zod — схемная валидация на TypeScript с runtime-проверкой.