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 отключает встроенную валидацию — убедитесь, что добавили собственную обработку.

Связанные темы

Ресурсы