CSS псевдокласс :invalid
Узнайте, как CSS :invalid стилизует поля формы, не прошедшие валидацию: примеры, подводные камни, доступность и поддержка браузерами.
Псевдокласс CSS :invalid соответствует элементам управления, связанным с формой — таким как <input>, <select> и <textarea> — чьё текущее значение не проходит встроенные ограничения валидации браузера. Это визуальная часть API ограничительной валидации HTML: браузер проверяет корректность значения, а :invalid позволяет стилизовать результат средствами чистого CSS, без JavaScript.
На этой странице рассматривается, когда именно :invalid срабатывает, как стилизовать его, не пугая пользователей до того, как они что-либо ввели, особый случай с переключателями (radio), современная альтернатива :user-invalid, а также способы сделать сообщения об ошибках доступными.
Когда элемент соответствует :invalid?
Элемент управления соответствует :invalid, когда он имеет хотя бы одно ограничение валидации, а текущее значение нарушает это ограничение. Распространённые причины срабатывания:
| Ограничение | Атрибут / тип | Не проходит, когда… |
|---|---|---|
| Обязательное, но пустое | required | поле не имеет значения |
| Неверный формат e-mail | type="email" | значение не является синтаксически корректным e-mail |
| Неверный формат URL | type="url" | значение не является допустимым абсолютным URL |
| Значение вне диапазона | min / max для type="number", type="date" и т.д. | значение выходит за пределы допустимого диапазона |
| Неверный шаг | step | значение не кратно интервалу шага |
| Несоответствие шаблону | pattern | значение не соответствует регулярному выражению |
| Слишком длинное / короткое | minlength / maxlength | длина значения выходит за пределы допустимого диапазона |
Если элемент управления не имеет ограничений (обычный <input type="text"> без дополнительных атрибутов), он считается неограниченным и ни :valid, ни :invalid к нему не применяются.
Элемент <fieldset> соответствует :invalid, если хотя бы один из его вложенных элементов формы невалиден.
Противоположную сторону см. в псевдоклассе :valid, который соответствует элементам, прошедшим все ограничения. Псевдокласс :required соответствует обязательным полям независимо от наличия значения.
Синтаксис
:invalid {
/* declarations applied to all invalid form controls */
}Ограничьте :invalid конкретным типом элемента, чтобы стили оставались предсказуемыми:
input:invalid,
textarea:invalid {
border: 2px solid #c00;
outline: none;
}Базовый пример
Поле e-mail ниже заполнено некорректным адресом ("not-an-email"), поэтому при загрузке оно соответствует input:invalid и получает красную рамку.
<!DOCTYPE html>
<html>
<head>
<title>:invalid example</title>
<style>
input:invalid {
border: 2px solid #c00;
background-color: #fff0f0;
}
input:valid {
border: 2px solid #090;
background-color: #f0fff0;
}
</style>
</head>
<body>
<h2>:invalid selector example</h2>
<form>
<label for="email">Email:</label>
<input id="email" type="email" value="not-an-email" required />
</form>
</body>
</html>Как избежать «преждевременного красного»
Самая распространённая ловушка :invalid: пустое обязательное поле уже является невалидным в момент загрузки страницы, поэтому новая форма может «загораться» красным ещё до того, как пользователь что-либо ввёл. Это выглядит как обвинение.
Вариант 1 — стилизовать только во время фокуса
Показывать рамку ошибки только пока пользователь находится в поле:
input:invalid:focus {
border-color: #c00;
outline: 2px solid #c00;
outline-offset: 1px;
}Это просто, но рамка исчезает, как только пользователь переключается на следующее поле, и пустое обязательное поле снова выглядит нормально.
Вариант 2 — скрывать ошибку, пока виден placeholder
:placeholder-shown равен true, когда отображается текст placeholder (то есть поле пустое). Комбинирование с :not заставляет стиль :invalid срабатывать только после того, как пользователь что-либо ввёл:
/* Only show the error style when the field has a value that is invalid */
input:invalid:not(:placeholder-shown) {
border-color: #c00;
}Это эффективно, но требует наличия атрибута placeholder у каждого поля — иначе :placeholder-shown никогда не будет истинным и защита не сработает.
Вариант 3 — использовать :user-invalid (современный стандарт)
Псевдокласс :user-invalid разработан именно для решения этой проблемы. Он ведёт себя как :invalid, но соответствует элементу только после того, как пользователь взаимодействовал с ним (вводил текст, потерял фокус или отправил форму):
/* Supported in all modern browsers as of 2024 */
input:user-invalid {
border-color: #c00;
}
/* Fallback for older browsers */
@supports not selector(:user-invalid) {
input:invalid:not(:placeholder-shown) {
border-color: #c00;
}
}:user-invalid — наиболее чистое решение, когда на него можно полагаться. Firefox поддерживает его как :-moz-ui-invalid уже давно; стандартный :user-invalid теперь поддерживается во всех современных браузерах.
Подход к стилизации
Жёсткая рамка 2 пк красного цвета читаема, но резка. Попробуйте сочетать изменение рамки с деликатным box-shadow для более мягкого вида:
input:invalid:not(:placeholder-shown) {
border-color: #c00;
box-shadow: 0 0 0 3px rgba(204, 0, 0, 0.15);
}Не полагайтесь только на цвет — см. раздел Доступность ниже.
Подводные камни
Переключатели (radio buttons)
Когда у одного из элементов группы переключателей задан атрибут required, все переключатели в группе соответствуют :invalid, пока ни один не выбран. Стилизовать маленькие кружки переключателей непрактично; вместо этого стилизуйте окружающий <fieldset> или <label>:
/* Style the fieldset, not the radio buttons themselves */
fieldset:invalid {
border: 2px solid #c00;
border-radius: 4px;
padding: 8px 12px;
}Все переключатели в группе имеют один и тот же атрибут name — именно это делает их группой в модели валидности браузера.
Пустые необязательные поля
Обычный <input type="text"> без required, pattern и ограничений по длине всегда является :valid, даже если он пуст. :invalid срабатывает только при наличии ограничения, которое нарушено.
select и textarea
<select> соответствует :invalid, если он является required и его текущее значение (value) — пустая строка (распространённый паттерн — placeholder <option value=""> «-- выберите --» в начале списка). <textarea> подчиняется тем же правилам, что и <input>, в отношении required, minlength и maxlength.
Firefox и :-moz-ui-invalid
Firefox давно применяет стили через :-moz-ui-invalid, который активируется только после взаимодействия пользователя — фактически это встроенное поведение :user-invalid. Если добавить собственные правила :invalid и проверить в Firefox, поле может выглядеть нормально (потому что в браузере включена стандартная защита от срабатывания без взаимодействия), а в Chrome — вести себя иначе (где такая защита по умолчанию отключена). Определите явные правила и используйте :user-invalid с fallback для единообразного поведения.
Доступность
Только цвета никогда недостаточно для сообщения об ошибке — пользователи с нарушениями цветовосприятия могут не заметить красную рамку. Сочетайте стилизацию :invalid с:
- Видимым текстовым сообщением, объясняющим, что пошло не так и как это исправить.
- Иконкой или символом рядом с изменением цвета (например, ✕ или значком предупреждения).
aria-invalid="true"на элементе управления, чтобы программы чтения с экрана объявляли его невалидным.aria-describedby, указывающим на элемент с сообщением об ошибке, чтобы описание читалось автоматически.
<label for="email">Email address</label>
<input
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
required
/>
<span id="email-error" role="alert">
Please enter a valid email address.
</span>Атрибут role="alert" на элементе с ошибкой заставляет программы чтения с экрана объявлять сообщение сразу после его появления в DOM, даже без фокуса.
Связанные псевдоклассы
| Псевдокласс | Соответствует, когда… |
|---|---|
:valid | элемент управления проходит все ограничения |
:required | элемент управления имеет атрибут required |
:optional | элемент управления не имеет required |
:out-of-range | значение числового/датового поля превышает min/max |
:in-range | значение числового/датового поля находится в пределах min/max |
:placeholder | текст placeholder элемента ввода |
:focus | элемент управления в данный момент имеет фокус клавиатуры |
Поддержка браузерами
:invalid является частью Selectors Level 4 и поддерживается во всех основных браузерах уже много лет. :user-invalid (вариант с учётом взаимодействия) появился в Chrome 119, Firefox 88 (а как :-moz-ui-invalid — значительно раньше) и Safari 16.5.
Подробнее о нативных атрибутах ограничительной валидации HTML см. в <input> и HTML Forms.