W3docs

CSS псевдокласс :invalid

Узнайте, как CSS :invalid стилизует поля формы, не прошедшие валидацию: примеры, подводные камни, доступность и поддержка браузерами.

Псевдокласс CSS :invalid соответствует элементам управления, связанным с формой — таким как <input>, <select> и <textarea> — чьё текущее значение не проходит встроенные ограничения валидации браузера. Это визуальная часть API ограничительной валидации HTML: браузер проверяет корректность значения, а :invalid позволяет стилизовать результат средствами чистого CSS, без JavaScript.

На этой странице рассматривается, когда именно :invalid срабатывает, как стилизовать его, не пугая пользователей до того, как они что-либо ввели, особый случай с переключателями (radio), современная альтернатива :user-invalid, а также способы сделать сообщения об ошибках доступными.

Когда элемент соответствует :invalid?

Элемент управления соответствует :invalid, когда он имеет хотя бы одно ограничение валидации, а текущее значение нарушает это ограничение. Распространённые причины срабатывания:

ОграничениеАтрибут / типНе проходит, когда…
Обязательное, но пустоеrequiredполе не имеет значения
Неверный формат e-mailtype="email"значение не является синтаксически корректным e-mail
Неверный формат URLtype="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.

Практика

Практика
Какова функция псевдокласса ':invalid' в CSS?
Какова функция псевдокласса ':invalid' в CSS?
Was this page helpful?