Стилизация валидных и невалидных состояний форм с помощью CSS
Пустые обязательные поля, светящиеся красным ещё до того, как пользователи введут хоть один символ. Это разочаровывающий опыт, который предлагают многие формы — и его можно полностью избежать с помощью современного CSS.
Это руководство охватывает состояния валидации форм CSS и псевдоклассы, которые ими управляют. Вы узнаете, когда использовать :valid и :invalid, почему :user-valid и :user-invalid обеспечивают лучший UX, и как стилизовать ошибки форм с помощью CSS, используя такие паттерны, как :has() для стилизации родительских элементов.
Ключевые выводы
- HTML5 constraint validation работает автоматически с атрибутами вроде
required,type,min,maxиpattern - Избегайте
:validи:invalidдля стилизации ошибок, так как они срабатывают до взаимодействия пользователя - Используйте
:user-validи:user-invalidдля отображения обратной связи по валидации только после того, как пользователи взаимодействуют с полями - Комбинируйте
:has()с псевдоклассами валидации для стилизации родительских элементов и управления видимостью сообщений об ошибках - Всегда сочетайте визуальную валидацию с ARIA-атрибутами для доступности программ чтения с экрана
Как работает Constraint Validation
HTML5 constraint validation происходит автоматически. Когда вы добавляете атрибуты вроде required, type="email", min, max, minlength, maxlength или pattern к полям форм, браузеры непрерывно оценивают валидность.
Браузер проверяет ограничения всякий раз, когда изменяется значение ввода. CSS-псевдоклассы отражают это состояние валидности в реальном времени, позволяя вам стилизовать поля в зависимости от того, проходят они валидацию или нет.
<input type="email" required minlength="5" />
Это поле становится невалидным, если оно пустое, если значение не отформатировано как email, или если оно короче пяти символов.
Основные CSS-псевдоклассы форм
:valid и :invalid
Эти псевдоклассы соответствуют полям на основе текущей валидности:
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
Проблема: :invalid применяется немедленно при загрузке страницы. Обязательное поле без значения технически невалидно до того, как пользователь к нему прикоснётся. Это создаёт плохой опыт — пользователи видят ошибки до того, как сделали что-то неправильно.
:required и :optional
Эти псевдоклассы нацелены на поля на основе атрибута required:
input:required {
border-left: 3px solid blue;
}
input:optional {
border-left: 3px solid gray;
}
Полезны для визуальных индикаторов, показывающих, какие поля должны быть заполнены.
:in-range и :out-of-range
Для числовых полей и полей диапазона с ограничениями min/max:
input:in-range {
background: white;
}
input:out-of-range {
background: #ffe0e0;
}
Лучший UX с :user-valid и :user-invalid
Псевдоклассы :user-valid и :user-invalid решают проблему преждевременных ошибок. Они соответствуют только после того, как пользователь взаимодействовал с полем — обычно после редактирования и потери фокуса.
input:user-invalid {
border-color: red;
}
input:user-valid {
border-color: green;
}
Теперь обязательные поля не показывают ошибки при загрузке страницы. Стилизация валидации появляется только после того, как пользователи получили возможность ввести данные. Это соответствует ожиданиям пользователей и снижает разочарование.
Эти псевдоклассы имеют широкую поддержку браузеров и должны быть вашим выбором по умолчанию для стилизации ошибок форм с помощью CSS.
Discover how at OpenReplay.com.
Стилизация родительских элементов с помощью :has()
Селектор :has() позволяет стилизовать родительские элементы на основе состояний валидации дочерних элементов — что ранее было невозможно без JavaScript.
<div class="field">
<label for="email">Email</label>
<input type="email" id="email" required />
<span class="error">Пожалуйста, введите корректный email</span>
</div>
.error {
display: none;
color: red;
}
.field:has(input:user-invalid) .error {
display: block;
}
.field:has(input:user-invalid) input {
border-color: red;
}
Этот паттерн показывает сообщения об ошибках только тогда, когда содержащийся внутри input не проходит валидацию после взаимодействия пользователя. Родительский контейнер управляет видимостью соседних элементов с ошибками.
Соображения доступности
Одной визуальной стилизации недостаточно для доступных форм. Пользователям программ чтения с экрана нужны программные ассоциации ошибок.
Сочетайте CSS-состояния валидации с правильными ARIA-атрибутами:
<div class="field">
<label for="email">Email</label>
<input
type="email"
id="email"
required
aria-describedby="email-error"
aria-invalid="false"
/>
<span id="email-error" class="error" aria-live="polite">
Пожалуйста, введите корректный email
</span>
</div>
Ключевые требования доступности:
aria-describedbyсвязывает input с его сообщением об ошибкеaria-live="polite"объявляет изменения ошибок программам чтения с экранаaria-invalidдолжен обновляться через JavaScript при неудачной валидации- Контраст цвета должен соответствовать требованиям WCAG (4.5:1 для текста)
- Не полагайтесь только на цвет — используйте иконки или текст наряду с изменениями цвета
Практический паттерн: полная валидация поля
Вот готовый к продакшену паттерн, комбинирующий эти техники:
/* Базовые стили полей */
.field input {
border: 2px solid #ccc;
transition: border-color 0.2s;
}
/* Валидное состояние после взаимодействия */
.field:has(input:user-valid) input {
border-color: #2e7d32;
}
/* Невалидное состояние после взаимодействия */
.field:has(input:user-invalid) input {
border-color: #c62828;
}
.field:has(input:user-invalid) .error {
display: block;
}
/* Сообщение об ошибке скрыто по умолчанию */
.error {
display: none;
color: #c62828;
font-size: 0.875rem;
margin-top: 0.25rem;
}
Этот подход держит сообщения об ошибках скрытыми до тех пор, пока пользователи не взаимодействуют с полями, затем показывает их только при неудачной валидации.
Заключение
Современные CSS-псевдоклассы форм обеспечивают мощную стилизацию валидации без JavaScript. Используйте :user-valid и :user-invalid как ваши основные инструменты — они предотвращают преждевременное отображение ошибок и соответствуют ожиданиям пользователей. Комбинируйте их с :has() для стилизации на уровне родителя, которая управляет видимостью сообщений об ошибках.
Помните, что визуальная стилизация дополняет, но не заменяет доступную обработку ошибок. Всегда сочетайте CSS-состояния валидации с соответствующими ARIA-атрибутами для пользователей программ чтения с экрана.
Часто задаваемые вопросы
Псевдокласс :invalid соответствует любому полю, которое не проходит валидацию, включая загрузку страницы до взаимодействия пользователя. Псевдокласс :user-invalid соответствует только после того, как пользователь взаимодействовал с полем и покинул его. Это предотвращает показ стилей ошибок на пустых обязательных полях до того, как пользователи получат возможность их заполнить.
Эти псевдоклассы имеют широкую поддержку в современных браузерах, включая Chrome, Firefox, Safari и Edge. Для поддержки старых браузеров рассмотрите использование псевдоклассов :focus и :not(:placeholder-shown) в качестве запасного паттерна, хотя этот подход менее точен.
CSS-псевдоклассы валидации отражают состояние constraint validation API браузера. Если вы предотвращаете стандартную отправку формы или используете JavaScript для обработки форм, убедитесь, что вызываете checkValidity() на элементах формы. CSS-состояния обновляются на основе свойства validity, а не попыток отправки.
Используйте селектор :has() на родительском контейнере для обнаружения состояний валидации дочерних input. Например, .field:has(input:user-invalid) .error-message позволяет показывать или скрывать соседние элементы с ошибками на основе того, не проходит ли валидацию input внутри этого контейнера после взаимодействия пользователя.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..