Нативные HTML-атрибуты валидации, о которых часто забывают разработчики
Вы пишете собственный JavaScript для валидации форм, хотя HTML может справиться с этим нативно. Большинство frontend-разработчиков знают required и pattern, но платформа предлагает гораздо больше — атрибуты, которые сокращают код, улучшают доступность и создают лучший UX без зависимостей от фреймворков.
В этой статье рассматриваются HTML-атрибуты валидации, которые вы, вероятно, упускаете из виду, а также CSS и JavaScript возможности, которые делают нативную валидацию форм действительно полезной.
Ключевые выводы
- Атрибут
formпозволяет элементам управления связываться с формами по ID, независимо от позиции в DOM, устраняя сложные структуры обёрток. - Атрибуты для отдельных кнопок, такие как
formaction,formmethodиformnovalidate, позволяют одной форме вести себя по-разному в зависимости от того, какая кнопка её отправляет. - Современные токены
autocomplete(new-password,one-time-code,webauthn) повышают точность автозаполнения и активируют функции браузера, такие как генераторы паролей. - CSS-псевдокласс
:user-invalidрешает проблему «красных границ при загрузке страницы», показывая ошибки только после взаимодействия пользователя. - Constraint Validation API (
setCustomValidity(),checkValidity(),reportValidity()) предоставляет программный контроль, когда нативная валидация требует расширения.
Атрибут form: элементы управления вне форм
Нужна кнопка отправки в шапке страницы, в то время как форма находится в основном контенте? Атрибут form позволяет любому элементу управления связаться с формой по ID, независимо от позиции в DOM.
<form id="checkout">
<input type="email" name="email" required>
</form>
<button type="submit" form="checkout">Завершить покупку</button>
Это устраняет необходимость в сложных обёртках и работает с input, button, select и textarea.
Переопределения для отдельных кнопок, о которых стоит знать
Одна форма может вести себя по-разному в зависимости от того, какая кнопка её отправляет. Эти атрибуты переопределяют настройки родительской формы:
formaction— отправка на другой URLformmethod— использование GET вместо POST (или наоборот)formenctype— изменение кодировки для загрузки файловformtarget— открытие ответа в новой вкладкеformnovalidate— полный пропуск валидации
Атрибут formnovalidate заслуживает особого внимания. Он необходим для кнопок «Сохранить черновик», где неполные данные допустимы.
Валидация по паттерну с понятными сообщениями об ошибках
Атрибут pattern принимает регулярные выражения, но браузеры по умолчанию показывают общие сообщения об ошибках. Используйте его вместе с title, чтобы предоставить контекст:
<input type="text"
pattern="[A-Z]{2}[0-9]{6}"
title="Формат: Две буквы, затем шесть цифр (например, AB123456)">
Примечание: когда для input установлен атрибут multiple, например type="email", паттерн применяется к каждому отдельному значению, а не ко всей строке, разделённой запятыми.
Современные токены autocomplete
Помимо on и off, autocomplete принимает семантические токены, которые повышают точность автозаполнения:
autocomplete="new-password"— активирует генераторы паролейautocomplete="one-time-code"— оптимизирован для SMS-верификацииautocomplete="webauthn"— сигнализирует о полях для passkey-учётных данных
Эти токены снижают трение и сигнализируют о намерениях браузерам и менеджерам паролей (полный список токенов см. в спецификации HTML и документации MDN по autocomplete).
Атрибут dirname для интернационализации
При поддержке языков с письмом справа налево dirname автоматически отправляет направление текста вместе со значением:
<input type="text" name="comment" dirname="comment.dir">
Форма отправляет и comment (значение), и comment.dir (ltr или rtl). Это необходимо для правильного отображения пользовательского контента.
Discover how at OpenReplay.com.
Нюанс readonly
Распространённое заблуждение: поля readonly участвуют в отправке формы, но ведут себя иначе при валидации. Они отправляют значения и могут получать фокус.
Однако элементы управления с readonly исключены из constraint validation в современном HTML. Это означает, что атрибуты вроде required, pattern, min или max игнорируются для целей валидации на readonly-полях во всех современных браузерах.
Если вам нужно отобразить значение без возможности редактирования и без отправки, disabled часто является лучшим выбором — хотя отключённые поля не отправляют свои значения.
CSS-псевдокласс :user-invalid для современного UX форм
Классический псевдокласс :invalid срабатывает немедленно, показывая ошибки до взаимодействия пользователя. Более новый :user-invalid срабатывает только после взаимодействия пользователя — решая проблему «красных границ при загрузке страницы».
input:user-invalid {
border-color: #dc3545;
}
input:user-valid {
border-color: #28a745;
}
Это создаёт лучший UX без логики таймингов на JavaScript. Поддержка браузерами сейчас надёжна во всех современных браузерах (см. :user-invalid на MDN).
Constraint Validation API
Когда нативная валидация требует расширения, Constraint Validation API предоставляет программный контроль:
checkValidity()— возвращает boolean, генерирует событиеinvalidпри неудачеreportValidity()— возвращает boolean и показывает нативный UI ошибокsetCustomValidity()— устанавливает пользовательские сообщения об ошибках
const password = document.querySelector('#password');
const confirm = document.querySelector('#confirm');
confirm.addEventListener('input', () => {
confirm.setCustomValidity(
password.value !== confirm.value ? 'Пароли должны совпадать' : ''
);
});
Вызовите setCustomValidity(''), чтобы очистить ошибки — передача любой непустой строки помечает поле как невалидное.
Когда нативная валидация недостаточна
Нативная валидация покрывает большинство случаев, но имеет ограничения:
- Кросс-полевая валидация (подтверждение пароля) требует JavaScript
- Стилизация сообщений об ошибках контролируется браузером
- Сложная асинхронная валидация (доступность имени пользователя) требует собственного кода
Стратегия: используйте HTML-атрибуты валидации как базовую линию, стилизуйте с помощью CSS :user-invalid и добавляйте Constraint Validation API только там, где это необходимо.
Заключение
Нативная валидация форм значительно развилась. Рассмотренные здесь атрибуты — form, переопределения для отдельных кнопок, dirname, современные токены autocomplete — устраняют значительную часть собственного JavaScript, одновременно улучшая доступность по умолчанию.
Проведите аудит существующих форм. Вы, вероятно, найдёте логику валидации, которую HTML обрабатывает нативно, и проблемы UX, которые CSS :user-invalid решает без единого обработчика событий.
Часто задаваемые вопросы
Нативные всплывающие сообщения об ошибках валидации имеют ограниченные возможности стилизации, контролируемые браузером. Вы не можете напрямую стилизовать их с помощью CSS. Для пользовательских стилизованных сообщений об ошибках вы можете отключить автоматический UI валидации, используя атрибут novalidate на форме, затем использовать Constraint Validation API для проверки валидности и отображения собственных элементов ошибок. Свойство validationMessage даёт вам доступ к тексту ошибки, сгенерированному браузером.
Да, нативные атрибуты валидации работают во фреймворках, поскольку они рендерят стандартный HTML. Однако фреймворки часто управляют состоянием формы иначе, что может конфликтовать с нативной валидацией. Многие разработчики используют атрибут novalidate и обрабатывают валидацию через состояние фреймворка. Вы всё ещё можете программно использовать Constraint Validation API внутри ваших компонентов для гибридного подхода.
Оба метода возвращают boolean, указывающий, проходит ли элемент ограничения валидации. Разница в побочных эффектах: checkValidity() только генерирует событие invalid при неудаче, в то время как reportValidity() также отображает нативный UI сообщения об ошибке браузера. Используйте checkValidity(), когда хотите проверить валидность незаметно, и reportValidity(), когда хотите, чтобы браузер показал пользователю обратную связь об ошибке.
Вы не можете проверить, что два поля совпадают, используя только HTML-атрибуты. Это требует JavaScript. Используйте Constraint Validation API, добавив обработчик события input к полю подтверждения, затем вызовите setCustomValidity() с сообщением об ошибке, когда значения различаются, или с пустой строкой, когда они совпадают. Это интегрирует вашу пользовательскую логику с нативной системой валидации.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.