Перейти к основному содержанию Перейти к навигации по документации
Check

Валидация

Предоставляйте пользователям ценные и полезные отзывы с помощью проверки формы HTML5, поведения браузера по умолчанию или пользовательских стилей и JavaScript.

Нам известно, что в настоящее время пользовательские стили проверки и всплывающие подсказки на стороне клиента недоступны, поскольку они не доступны для вспомогательных технологий. Пока мы работаем над решением, мы рекомендуем либо использовать вариант на стороне сервера, либо метод проверки браузера по умолчанию.

Как это устроено

Вот как проверка формы работает с Bootstrap:

  • Проверка HTML-формы применяется через два псевдокласса CSS, :invalid и :valid. Это применимо к элементам <input>, <select> и <textarea>.
  • Bootstrap переносит стили :invalid и :valid в родительский класс .was-validated, обычно применяемый к <form>. В противном случае любое обязательное поле без значения будет отображаться как недопустимое при загрузке страницы. Таким образом, Вы можете выбрать, когда их активировать (обычно после попытки отправки формы).
  • Чтобы сбросить внешний вид формы (например, в случае отправки динамической формы с использованием AJAX), удалите класс .was-validated из <form> снова после отправки.
  • Вместо псевдоклассов для проверки на стороне сервера, могут использоваться классы .is-invalid и .is-valid. Им не нужен родительский класс .was-validated.
  • Из-за ограничений в том, как работает CSS, мы не можем (в настоящее время) применять стили <label>, который находится перед элементом управления формой в DOM без помощи пользовательского JavaScript.
  • Все современные браузеры поддерживают API проверки ограничений, серию методов JavaScript для проверки элементов управления формы.
  • В сообщениях обратной связи могут использоваться параметры браузера по умолчанию (разные для каждого браузера и нестандартные с помощью CSS) или наши пользовательские стили обратной связи с дополнительным HTML и CSS.
  • Вы можете предоставлять настраиваемые сообщения о действительности с помощью setCustomValidity в JavaScript.

Имея это в виду, рассмотрим следующие демонстрации наших пользовательских стилей проверки формы, необязательных серверных классов и настроек браузера по умолчанию.

Пользовательские стили

Для настраиваемых сообщений проверки формы Bootstrap Вам необходимо добавить логический атрибут novalidate к Вашему <form>. Это отключает всплывающие подсказки обратной связи браузера по умолчанию, но по-прежнему обеспечивает доступ к API проверки формы в JavaScript. Попробуйте отправить форму ниже; наш JavaScript перехватит кнопку отправки и передаст Вам ответную реакцию. При попытке отправить Вы увидите стили: :invalid и :valid, примененные к элементам управления Вашей формы.

В пользовательских стилях обратной связи применяются пользовательские цвета, границы, стили фокуса и фоновые иконки, чтобы лучше передавать обратную связь. Фоновые иконки для <select> доступны только с .form-select, но не с .form-control.

Все хорошо!
Все хорошо!
@
Пожалуйста, выберите имя пользователя.
Укажите действующий город.
Пожалуйста, выберите корректный город.
Пожалуйста, предоставьте действующий почтовый индекс.
Вы должны принять перед отправкой.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4">
    <label for="validationCustom01" class="form-label">Имя</label>
    <input type="text" class="form-control" id="validationCustom01" value="Иван" required>
    <div class="valid-feedback">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustom02" class="form-label">Фамилия</label>
    <input type="text" class="form-control" id="validationCustom02" value="Петров" required>
    <div class="valid-feedback">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustomUsername" class="form-label">Имя пользователя</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="inputGroupPrepend">@</span>
      <input type="text" class="form-control" id="validationCustomUsername" aria-describedby="inputGroupPrepend" required>
      <div class="invalid-feedback">
        Пожалуйста, выберите имя пользователя.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationCustom03" class="form-label">Город</label>
    <input type="text" class="form-control" id="validationCustom03" required>
    <div class="invalid-feedback">
      Укажите действующий город.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom04" class="form-label">Область</label>
    <select class="form-select" id="validationCustom04" required>
      <option selected disabled value="">Выберите...</option>
      <option>...</option>
    </select>
    <div class="invalid-feedback">
      Пожалуйста, выберите корректный город.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom05" class="form-label">Индекс</label>
    <input type="text" class="form-control" id="validationCustom05" required>
    <div class="invalid-feedback">
      Пожалуйста, предоставьте действующий почтовый индекс.
    </div>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>
      <label class="form-check-label" for="invalidCheck">
        Примите условия и соглашения
      </label>
      <div class="invalid-feedback">
        Вы должны принять перед отправкой.
      </div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Отправить форму</button>
  </div>
</form>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(() => {
  'use strict'

  // Fetch all the forms we want to apply custom Bootstrap validation styles to
  const forms = document.querySelectorAll('.needs-validation')

  // Loop over them and prevent submission
  Array.from(forms).forEach(form => {
    form.addEventListener('submit', event => {
      if (!form.checkValidity()) {
        event.preventDefault()
        event.stopPropagation()
      }

      form.classList.add('was-validated')
    }, false)
  })
})()

Настройки браузера по умолчанию

Не заинтересованы в пользовательских сообщениях обратной связи для проверки или написании JavaScript для изменения поведения формы? Все хорошо, Вы можете использовать настройки браузера по умолчанию. Попробуйте заполнить форму ниже. В зависимости от Вашего браузера и ОС Вы увидите немного другой стиль обратной связи.

Хотя эти стили обратной связи нельзя стилизовать с помощью CSS, Вы все равно можете настроить текст отзыва с помощью JavaScript.

@
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationDefault01" class="form-label">Имя</label>
    <input type="text" class="form-control" id="validationDefault01" value="Иван" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefault02" class="form-label">Фамилия</label>
    <input type="text" class="form-control" id="validationDefault02" value="Петров" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefaultUsername" class="form-label">Имя пользователя</label>
    <div class="input-group">
      <span class="input-group-text" id="inputGroupPrepend2">@</span>
      <input type="text" class="form-control" id="validationDefaultUsername"  aria-describedby="inputGroupPrepend2" required>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationDefault03" class="form-label">Город</label>
    <input type="text" class="form-control" id="validationDefault03" required>
  </div>
  <div class="col-md-3">
    <label for="validationDefault04" class="form-label">Область</label>
    <select class="form-select" id="validationDefault04" required>
      <option selected disabled value="">Выберите...</option>
      <option>...</option>
    </select>
  </div>
  <div class="col-md-3">
    <label for="validationDefault05" class="form-label">Индекс</label>
    <input type="text" class="form-control" id="validationDefault05" required>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" id="invalidCheck2" required>
      <label class="form-check-label" for="invalidCheck2">
        Примите условия и соглашения
      </label>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Отправить форму</button>
  </div>
</form>

На стороне сервера

Мы рекомендуем использовать проверку на стороне клиента, но если Вам требуется проверка на стороне сервера, Вы можете указать недопустимые и допустимые поля формы с помощью .is-invalid и .is-valid. Обратите внимание, что эти классы также поддерживают .invalid-feedback.

Для недопустимых полей убедитесь, что недопустимая обратная связь/сообщение об ошибке связано с соответствующим полем формы с помощью aria-describedby (отмечая, что этот атрибут позволяет ссылаться на более чем один id, в случае если поле уже указывает на дополнительную форму текст).

Чтобы исправить проблемы с радиусами границ, для групп ввода требуется дополнительный класс .has-validation.

To fix issues with border radii, input groups require an additional .has-validation class.

Все хорошо!
Все хорошо!
@
Пожалуйста, выберите имя пользователя.
Укажите действующий город.
Пожалуйста, выберите корректный город.
Пожалуйста, предоставьте действующий почтовый индекс.
Вы должны принять перед отправкой.
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationServer01" class="form-label">Имя</label>
    <input type="text" class="form-control is-valid" id="validationServer01" value="Иван" required>
    <div class="valid-feedback">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServer02" class="form-label">Фамилия</label>
    <input type="text" class="form-control is-valid" id="validationServer02" value="Петров" required>
    <div class="valid-feedback">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServerUsername" class="form-label">Имя пользователя</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="inputGroupPrepend3">@</span>
      <input type="text" class="form-control is-invalid" id="validationServerUsername" aria-describedby="inputGroupPrepend3 validationServerUsernameFeedback" required>
      <div id="validationServerUsernameFeedback" class="invalid-feedback">
        Пожалуйста, выберите имя пользователя.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationServer03" class="form-label">Город</label>
    <input type="text" class="form-control is-invalid" id="validationServer03" aria-describedby="validationServer03Feedback" required>
    <div id="validationServer03Feedback" class="invalid-feedback">
      Укажите действующий город.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer04" class="form-label">Область</label>
    <select class="form-select is-invalid" id="validationServer04" aria-describedby="validationServer04Feedback" required>
      <option selected disabled value="">Выберите...</option>
      <option>...</option>
    </select>
    <div id="validationServer04Feedback" class="invalid-feedback">
      Пожалуйста, выберите корректный город.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer05" class="form-label">Индекс</label>
    <input type="text" class="form-control is-invalid" id="validationServer05" aria-describedby="validationServer05Feedback" required>
    <div id="validationServer05Feedback" class="invalid-feedback">
      Пожалуйста, предоставьте действующий почтовый индекс.
    </div>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input is-invalid" type="checkbox" value="" id="invalidCheck3" aria-describedby="invalidCheck3Feedback" required>
      <label class="form-check-label" for="invalidCheck3">
        Примите условия и соглашения
      </label>
      <div id="invalidCheck3Feedback" class="invalid-feedback">
        Вы должны принять перед отправкой.
      </div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Отправить форму</button>
  </div>
</form>

Поддерживаемые элементы

Проверка стилей доступна для следующих элементов управления и компонентов формы:

  • <input> и <textarea> с .form-control (включая .form-control в группе ввода)
  • <select> с .form-select
  • .form-check
Пожалуйста, введите сообщение в текстовое поле.
Пример неверного текста обратной связи
Еще пример неверного текста обратной связи
Пример обратной связи неверного выбора
Пример обратной связи неверной формы выбора файла
html
<form class="was-validated">
  <div class="mb-3">
    <label for="validationTextarea" class="form-label">Текстовое поле</label>
    <textarea class="form-control" id="validationTextarea" placeholder="Обязательный пример текстового поля" required></textarea>
    <div class="invalid-feedback">
      Пожалуйста, введите сообщение в текстовое поле.
    </div>
  </div>

  <div class="form-check mb-3">
    <input type="checkbox" class="form-check-input" id="validationFormCheck1" required>
    <label class="form-check-label" for="validationFormCheck1">Отметьте этот флажок</label>
    <div class="invalid-feedback">Пример неверного текста обратной связи</div>
  </div>

  <div class="form-check">
    <input type="radio" class="form-check-input" id="validationFormCheck2" name="radio-stacked" required>
    <label class="form-check-label" for="validationFormCheck2">Переключить это радио</label>
  </div>
  <div class="form-check mb-3">
    <input type="radio" class="form-check-input" id="validationFormCheck3" name="radio-stacked" required>
    <label class="form-check-label" for="validationFormCheck3">Или переключить это другое радио</label>
    <div class="invalid-feedback">Еще пример неверного текста обратной связи</div>
  </div>

  <div class="mb-3">
    <select class="form-select" required aria-label="select example">
      <option value="">Откройте это меню выбора</option>
      <option value="1">Один</option>
      <option value="2">Два</option>
      <option value="3">Три</option>
    </select>
    <div class="invalid-feedback">Пример обратной связи неверного выбора </div>
  </div>

  <div class="mb-3">
    <input type="file" class="form-control" aria-label="file example" required>
    <div class="invalid-feedback">Пример обратной связи неверной формы выбора файла</div>
  </div>

  <div class="mb-3">
    <button class="btn btn-primary" type="submit" disabled>Отправить форму</button>
  </div>
</form>

Всплывающие подсказки

Если Ваш макет формы позволяет это, Вы можете заменить классы .{valid|invalid}-feedback на классы .{valid|invalid}-tooltip , чтобы отображать отзывы о проверке в стилизованной всплывающей подсказке. Убедитесь, что у Вас есть родительский элемент с position: relative для позиционирования всплывающей подсказки. В приведенном ниже примере у наших классов столбцов это уже есть, но для Вашего проекта может потребоваться альтернативная настройка.

Все хорошо!
Все хорошо!
@
Пожалуйста, выберите уникальное и действительное имя пользователя.
Укажите действующий город.
Пожалуйста, выберите корректный город.
Пожалуйста, предоставьте действующий почтовый индекс.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip01" class="form-label">Имя</label>
    <input type="text" class="form-control" id="validationTooltip01" value="Иван" required>
    <div class="valid-tooltip">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip02" class="form-label">Фамилия</label>
    <input type="text" class="form-control" id="validationTooltip02" value="Петров" required>
    <div class="valid-tooltip">
      Все хорошо!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltipUsername" class="form-label">Имя пользователя</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="validationTooltipUsernamePrepend">@</span>
      <input type="text" class="form-control" id="validationTooltipUsername" aria-describedby="validationTooltipUsernamePrepend" required>
      <div class="invalid-tooltip">
        Пожалуйста, выберите уникальное и действительное имя пользователя.
      </div>
    </div>
  </div>
  <div class="col-md-6 position-relative">
    <label for="validationTooltip03" class="form-label">Город</label>
    <input type="text" class="form-control" id="validationTooltip03" required>
    <div class="invalid-tooltip">
      Укажите действующий город.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip04" class="form-label">Область</label>
    <select class="form-select" id="validationTooltip04" required>
      <option selected disabled value="">Выберите...</option>
      <option>...</option>
    </select>
    <div class="invalid-tooltip">
      Пожалуйста, выберите корректный город.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip05" class="form-label">Индекс</label>
    <input type="text" class="form-control" id="validationTooltip05" required>
    <div class="invalid-tooltip">
      Пожалуйста, предоставьте действующий почтовый индекс.
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Отправить форму</button>
  </div>
</form>

Sass

Переменные

$form-feedback-margin-top:          $form-text-margin-top;
$form-feedback-font-size:           $form-text-font-size;
$form-feedback-font-style:          $form-text-font-style;
$form-feedback-valid-color:         $success;
$form-feedback-invalid-color:       $danger;

$form-feedback-icon-valid-color:    $form-feedback-valid-color;
$form-feedback-icon-valid:          url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>");
$form-feedback-icon-invalid-color:  $form-feedback-invalid-color;
$form-feedback-icon-invalid:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='#{$form-feedback-icon-invalid-color}'><circle cx='6' cy='6' r='4.5'/><path stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/><circle cx='6' cy='8.2' r='.6' fill='#{$form-feedback-icon-invalid-color}' stroke='none'/></svg>");

Миксины

Два миксина объединяются вместе с помощью нашего цикла, чтобы сгенерировать наши стили обратной связи для проверки формы.

@mixin form-validation-state-selector($state) {
  @if ($state == "valid" or $state == "invalid") {
    .was-validated #{if(&, "&", "")}:#{$state},
    #{if(&, "&", "")}.is-#{$state} {
      @content;
    }
  } @else {
    #{if(&, "&", "")}.is-#{$state} {
      @content;
    }
  }
}

@mixin form-validation-state(
  $state,
  $color,
  $icon,
  $tooltip-color: color-contrast($color),
  $tooltip-bg-color: rgba($color, $form-feedback-tooltip-opacity),
  $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($color, $input-btn-focus-color-opacity)
) {
  .#{$state}-feedback {
    display: none;
    width: 100%;
    margin-top: $form-feedback-margin-top;
    @include font-size($form-feedback-font-size);
    font-style: $form-feedback-font-style;
    color: $color;
  }

  .#{$state}-tooltip {
    position: absolute;
    top: 100%;
    z-index: 5;
    display: none;
    max-width: 100%; // Contain to parent when possible
    padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
    margin-top: .1rem;
    @include font-size($form-feedback-tooltip-font-size);
    line-height: $form-feedback-tooltip-line-height;
    color: $tooltip-color;
    background-color: $tooltip-bg-color;
    @include border-radius($form-feedback-tooltip-border-radius);
  }

  @include form-validation-state-selector($state) {
    ~ .#{$state}-feedback,
    ~ .#{$state}-tooltip {
      display: block;
    }
  }

  .form-control {
    @include form-validation-state-selector($state) {
      border-color: $color;

      @if $enable-validation-icons {
        padding-right: $input-height-inner;
        background-image: escape-svg($icon);
        background-repeat: no-repeat;
        background-position: right $input-height-inner-quarter center;
        background-size: $input-height-inner-half $input-height-inner-half;
      }

      &:focus {
        border-color: $color;
        box-shadow: $focus-box-shadow;
      }
    }
  }

  // stylelint-disable-next-line selector-no-qualifying-type
  textarea.form-control {
    @include form-validation-state-selector($state) {
      @if $enable-validation-icons {
        padding-right: $input-height-inner;
        background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
      }
    }
  }

  .form-select {
    @include form-validation-state-selector($state) {
      border-color: $color;

      @if $enable-validation-icons {
        &:not([multiple]):not([size]),
        &:not([multiple])[size="1"] {
          padding-right: $form-select-feedback-icon-padding-end;
          background-image: escape-svg($form-select-indicator), escape-svg($icon);
          background-position: $form-select-bg-position, $form-select-feedback-icon-position;
          background-size: $form-select-bg-size, $form-select-feedback-icon-size;
        }
      }

      &:focus {
        border-color: $color;
        box-shadow: $focus-box-shadow;
      }
    }
  }

  .form-control-color {
    @include form-validation-state-selector($state) {
      @if $enable-validation-icons {
        width: add($form-color-width, $input-height-inner);
      }
    }
  }

  .form-check-input {
    @include form-validation-state-selector($state) {
      border-color: $color;

      &:checked {
        background-color: $color;
      }

      &:focus {
        box-shadow: $focus-box-shadow;
      }

      ~ .form-check-label {
        color: $color;
      }
    }
  }
  .form-check-inline .form-check-input {
    ~ .#{$state}-feedback {
      margin-left: .5em;
    }
  }

  .input-group {
    > .form-control:not(:focus),
    > .form-select:not(:focus),
    > .form-floating:not(:focus-within) {
      @include form-validation-state-selector($state) {
        @if $state == "valid" {
          z-index: 3;
        } @else if $state == "invalid" {
          z-index: 4;
        }
      }
    }
  }
}

Карта

Это карта валидации Sass из _variables.scss. Переопределите или расширьте это, чтобы создать другие или дополнительные состояния.

$form-validation-states: (
  "valid": (
    "color": $form-feedback-valid-color,
    "icon": $form-feedback-icon-valid
  ),
  "invalid": (
    "color": $form-feedback-invalid-color,
    "icon": $form-feedback-icon-invalid
  )
);

Карты $form-validation-states могут содержать три необязательных параметра для переопределения всплывающих подсказок и стилей фокуса.

Цикл

Используется для перебора значений карты $form-validation-states для генерации наших стилей проверки. Любые изменения в приведенной выше карте Sass будут отражены в Вашем скомпилированном CSS через этот цикл.

@each $state, $data in $form-validation-states {
  @include form-validation-state($state, $data...);
}

Кастомизация

Состояния проверки можно настроить через Sass с помощью карты $form-validation-states. Эта карта Sass, расположенная в нашем файле _variables.scss, используется для генерации состояний валидации по умолчанию valid/invalid. ключена вложенная карта для настройки цвета каждого состояния, иконки, цвета всплывающей подсказки и тени фокуса. Хотя браузеры не поддерживают никакие другие состояния, те, кто использует собственные стили, могут легко добавить более сложную обратную связь с формой.