Constraint Validation API
Constraint Validation API — браузерный API для валидации HTML-форм, позволяющий проверять поля через атрибуты (
required,pattern,min,max) и программно управлять состоянием ошибок через методы элементов формы.
Зачем нужно
Встроенная браузерная валидация через атрибуты (required, type="email", pattern) работает «из коробки» без единой строки JavaScript. Constraint Validation API даёт программный доступ к тем же механизмам: можно проверить валидность поля, получить текст ошибки, задать кастомное сообщение и стилизовать состояния через CSS-псевдоклассы :valid/:invalid. Это позволяет строить доступные (a11y) формы без тяжёлых библиотек.
Где используется
- Формы регистрации и входа: валидация email, пароля, телефона
- Проверка перед отправкой без полного перехода на JavaScript-валидацию
- Кастомные сообщения об ошибках через
setCustomValidity - Условная валидация: показывать ошибку только после попытки отправки (touched state)
- Доступные формы: браузерные ARIA-атрибуты и нативные подсказки
Основной контент
HTML-атрибуты валидации
<form id="registrationForm">
<!-- required — поле обязательно -->
<input type="text" name="name" required minlength="2" maxlength="50">
<!-- type="email" — встроенная проверка формата email -->
<input type="email" name="email" required>
<!-- pattern — регулярное выражение -->
<input type="text" name="phone" pattern="\+7\d{10}"
title="Введите номер в формате +71234567890">
<!-- min/max для чисел и дат -->
<input type="number" name="age" min="18" max="100" required>
<button type="submit">Зарегистрироваться</button>
</form>
Программный доступ через API
const form = document.getElementById('registrationForm');
const emailInput = form.querySelector('[name="email"]');
// checkValidity — проверка валидности (без показа UI)
console.log(emailInput.checkValidity); // false если невалидно
// validity — объект ValidityState
const v = emailInput.validity;
console.log(v.valid); // true если всё ок
console.log(v.valueMissing); // true если required не заполнен
console.log(v.typeMismatch); // true если неверный тип (email, url)
console.log(v.patternMismatch); // true если pattern не совпал
console.log(v.tooShort); // true если меньше minlength
console.log(v.tooLong); // true если больше maxlength
console.log(v.rangeUnderflow); // true если меньше min
console.log(v.rangeOverflow); // true если больше max
// validationMessage — текст ошибки браузера
console.log(emailInput.validationMessage); // "Введите корректный email"
// setCustomValidity — кастомная ошибка
emailInput.setCustomValidity('Email уже зарегистрирован');
emailInput.checkValidity; // false
emailInput.setCustomValidity(''); // сбросить кастомную ошибку
Кастомная валидация с нативным UI
// Показывать ошибки только после попытки отправки (UX-паттерн)
form.addEventListener('submit', (e) => {
e.preventDefault();
if (!form.checkValidity) {
// reportValidity — показывает нативные подсказки браузера
form.reportValidity;
return;
}
// Форма валидна — отправляем
submitForm(new FormData(form));
});
// Кастомная асинхронная валидация (уникальность email)
const emailField = form.querySelector('[name="email"]');
emailField.addEventListener('blur', async () => {
const email = emailField.value;
if (!emailField.validity.typeMismatch && email) {
const taken = await checkEmailExists(email);
emailField.setCustomValidity(taken ? 'Email уже используется' : '');
// Можно вызвать reportValidity для показа подсказки
}
});
CSS-стилизация состояний
/* Стилизация только после взаимодействия (через :user-invalid, CSS 4) */
input:user-invalid {
border-color: red;
}
/* Или через JS-класс "touched" */
input.touched:invalid {
border-color: red;
background: #fff0f0;
}
input:valid {
border-color: green;
}
Частые ошибки
setCustomValidity('')не вызван для сброса: если установить кастомную ошибку и не сбросить после исправления, поле останется невалидным навсегда.- Полагаться только на HTML-атрибуты: серверная валидация обязательна — клиентская защищает UX, но не безопасность.
checkValidityбезreportValidity:checkValidityпроверяет, но не показывает UI-подсказки — для показа нуженreportValidity.novalidateна форме без своей валидации: атрибутnovalidateотключает встроенную валидацию — убедитесь, что добавили собственную обработку.