Skip to main content Skip to docs navigation

Validación (Validation)

Proporciona comentarios valiosos y prácticos a tus usuarios con la validación de formularios HTML5, mediante comportamientos predeterminados del navegador o estilos personalizados y JavaScript.

Somos conscientes de que actualmente los estilos de validación personalizados del lado del cliente y los tooltips no son accesibles, ya que no están expuestos a tecnologías de asistencia. Mientras trabajamos en una solución, recomendamos utilizar la opción del lado del servidor o el método de validación predeterminado del navegador.

Cómo funciona

Así es como funciona la validación de formularios con Bootstrap:

  • La validación de formularios HTML se aplica a través de las dos pseudoclases de CSS, :invalid y :valid. Se aplica a los elementos <input>, <select> y <textarea>.
  • Bootstrap limita los estilos :invalid y :valid a la clase del elemento padre .was-validated, que generalmente se aplica al <form>. De lo contrario, cualquier campo requerido sin un valor aparece como no válido al cargar la página. De esta manera, puedes elegir cuándo activarlos (normalmente después de intentar enviar el formulario).
  • Para restablecer la apariencia del formulario (por ejemplo, en el caso de envíos de formularios dinámicos utilizando Ajax), retira la clase .was-validated del <form> nuevamente después del envío.
  • Como alternativa, se pueden usar las clases .is-invalid y .is-valid en lugar de las pseudoclases para la validación del lado del servidor. No requieren una clase padre .was-validated.
  • Debido a las limitaciones de cómo funciona CSS, no podemos (en la actualidad) aplicar estilos a un <label> que va antes de un control de formulario en el DOM sin la ayuda de JavaScript personalizado.
  • Todos los navegadores modernos admiten la constraint validation API, una serie de métodos JavaScript para validar controles de formulario.
  • Los mensajes de respuesta pueden utilizar los valores predeterminados del navegador (diferentes para cada navegador y que no se pueden diseñar mediante CSS) o nuestros estilos de respuesta personalizados con HTML y CSS adicionales.
  • Puedes proporcionar mensajes de validez personalizados con setCustomValidity en JavaScript.

Con esto en mente, considera las siguientes demostraciones para nuestros estilos personalizados de validación de formularios, clases opcionales del lado del servidor y valores predeterminados del navegador.

Estilos personalizados

Para los mensajes de validación de formulario personalizados de Bootstrap, deberás agregar el atributo booleano novalidate a tu <form>. Esto desactiva los tooltips de respuesta predeterminados del navegador, pero aún proporciona acceso a las API de validación de formularios en JavaScript. Intenta enviar el formulario a continuación; nuestro JavaScript interceptará el botón de envío y te transmitirá la respuesta. Al intentar enviar, verás los estilos :invalid y :valid aplicados a tus controles de formulario.

Los estilos de respuesta personalizados aplican colores, bordes, estilos de enfoque e iconos de fondo personalizados para comunicar mejor los comentarios. Los iconos de fondo para los selectores <select> solo están disponibles con .form-select, y no con .form-control.

¡Se ve bien!
¡Se ve bien!
@
Por favor elige un nombre de usuario.
Por favor proporciona una ciudad válida.
Por favor selecciona un estado válido.
Por favor proporciona un código postal válido.
Debes estar de acuerdo antes de enviar.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4">
    <label for="validationCustom01" class="form-label">Nombre</label>
    <input type="text" class="form-control" id="validationCustom01" value="Mark" required>
    <div class="valid-feedback">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustom02" class="form-label">Apellido</label>
    <input type="text" class="form-control" id="validationCustom02" value="Otto" required>
    <div class="valid-feedback">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustomUsername" class="form-label">Nombre de usuario</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">
        Por favor elige un nombre de usuario.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationCustom03" class="form-label">Ciudad</label>
    <input type="text" class="form-control" id="validationCustom03" required>
    <div class="invalid-feedback">
      Por favor proporciona una ciudad válida.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom04" class="form-label">Estado</label>
    <select class="form-select" id="validationCustom04" required>
      <option selected disabled value="">Elige...</option>
      <option>...</option>
    </select>
    <div class="invalid-feedback">
      Por favor selecciona un estado válido.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom05" class="form-label">Código postal</label>
    <input type="text" class="form-control" id="validationCustom05" required>
    <div class="invalid-feedback">
      Por favor proporciona un código postal válido.
    </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">
        Acepto los términos y condiciones
      </label>
      <div class="invalid-feedback">
        Debes estar de acuerdo antes de enviar.
      </div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Enviar formulario</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)
  })
})()

Valores predeterminados del navegador

¿No estás interesado en mensajes de respuesta de validación personalizados ni en escribir JavaScript para cambiar los comportamientos del formulario? No hay problema, puedes utilizar los valores predeterminados del navegador. Intenta enviar el formulario a continuación. Según tu navegador y sistema operativo, verás un estilo de respuesta ligeramente diferente.

Aunque estos estilos de respuesta no se pueden diseñar con CSS, puedes personalizar el texto a través de JavaScript.

@
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationDefault01" class="form-label">Nombre</label>
    <input type="text" class="form-control" id="validationDefault01" value="Mark" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefault02" class="form-label">Apellido</label>
    <input type="text" class="form-control" id="validationDefault02" value="Otto" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefaultUsername" class="form-label">Nombre de usuario</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">Ciudad</label>
    <input type="text" class="form-control" id="validationDefault03" required>
  </div>
  <div class="col-md-3">
    <label for="validationDefault04" class="form-label">Estado</label>
    <select class="form-select" id="validationDefault04" required>
      <option selected disabled value="">Elige...</option>
      <option>...</option>
    </select>
  </div>
  <div class="col-md-3">
    <label for="validationDefault05" class="form-label">Código postal</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">
        Acepto los términos y condiciones
      </label>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Enviar formulario</button>
  </div>
</form>

Del lado del servidor (Server-side)

Recomendamos utilizar la validación del lado del cliente, pero en caso de que necesites validación del lado del servidor, puedes indicar campos de formulario válidos y no válidos con .is-invalid y .is-valid. Ten en cuenta que .invalid-feedback también es compatible con estas clases.

Para campos no válidos, asegúrate de que el mensaje de error/respuesta no válida esté asociado con el campo de formulario correspondiente usando aria-describedby (teniendo en cuenta que este atributo permite hacer referencia a más de un id, en caso de que el campo ya apunte a texto de formulario adicional).

Para solucionar los problemas con el radio del borde, los grupos de entrada requieren una clase .has-validation adicional.

¡Se ve bien!
¡Se ve bien!
@
Por favor elige un nombre de usuario.
Por favor proporciona una ciudad válida.
Por favor selecciona un estado válido.
Por favor proporciona un código postal válido.
Debes estar de acuerdo antes de enviar.
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationServer01" class="form-label">Nombre</label>
    <input type="text" class="form-control is-valid" id="validationServer01" value="Mark" required>
    <div class="valid-feedback">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServer02" class="form-label">Apellido</label>
    <input type="text" class="form-control is-valid" id="validationServer02" value="Otto" required>
    <div class="valid-feedback">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServerUsername" class="form-label">Nombre de usuario</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">
        Por favor elige un nombre de usuario.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationServer03" class="form-label">Ciudad</label>
    <input type="text" class="form-control is-invalid" id="validationServer03" aria-describedby="validationServer03Feedback" required>
    <div id="validationServer03Feedback" class="invalid-feedback">
      Por favor proporciona una ciudad válida.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer04" class="form-label">Estado</label>
    <select class="form-select is-invalid" id="validationServer04" aria-describedby="validationServer04Feedback" required>
      <option selected disabled value="">Elige...</option>
      <option>...</option>
    </select>
    <div id="validationServer04Feedback" class="invalid-feedback">
      Por favor selecciona un estado válido.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer05" class="form-label">Código postal</label>
    <input type="text" class="form-control is-invalid" id="validationServer05" aria-describedby="validationServer05Feedback" required>
    <div id="validationServer05Feedback" class="invalid-feedback">
      Por favor proporciona un código postal válido.
    </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">
        Acepto los términos y condiciones
      </label>
      <div id="invalidCheck3Feedback" class="invalid-feedback">
        Debes estar de acuerdo antes de enviar.
      </div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Enviar formulario</button>
  </div>
</form>

Elementos admitidos

Los estilos de validación están disponibles para los siguientes controles y componentes de formulario:

  • Elementos <input> y <textarea> con .form-control (incluyendo hasta un .form-control en grupos de entrada)
  • Selectores <select> con .form-select
  • Elementos .form-check
Por favor ingresa un mensaje en el área de texto.
Texto de respuesta no válida de ejemplo
Más texto de respuesta no válida de ejemplo
Respuesta de selección no válida de ejemplo
Respuesta de archivo de formulario no válida de ejemplo
html
<form class="was-validated">
  <div class="mb-3">
    <label for="validationTextarea" class="form-label">Área de texto</label>
    <textarea class="form-control" id="validationTextarea" placeholder="Área de texto de ejemplo obligatoria" required></textarea>
    <div class="invalid-feedback">
      Por favor ingresa un mensaje en el área de texto.
    </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">Marca esta casilla de verificación</label>
    <div class="invalid-feedback">Texto de respuesta no válida de ejemplo</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">Alterna este botón de opción</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">O alterna este otro botón de opción</label>
    <div class="invalid-feedback">Más texto de respuesta no válida de ejemplo</div>
  </div>

  <div class="mb-3">
    <select class="form-select" required aria-label="select example">
      <option value="">Abre este menú de selección</option>
      <option value="1">Uno</option>
      <option value="2">Dos</option>
      <option value="3">Tres</option>
    </select>
    <div class="invalid-feedback">Respuesta de selección no válida de ejemplo</div>
  </div>

  <div class="mb-3">
    <input type="file" class="form-control" aria-label="file example" required>
    <div class="invalid-feedback">Respuesta de archivo de formulario no válida de ejemplo</div>
  </div>

  <div class="mb-3">
    <button class="btn btn-primary" type="submit" disabled>Enviar formulario</button>
  </div>
</form>

Tooltips

Si el diseño de tu formulario lo permite, puedes cambiar las clases .{valid|invalid}-feedback por las clases .{valid|invalid}-tooltip para mostrar la respuesta de validación en un tooltip con estilo. Asegúrate de tener un elemento padre con position: relative para el posicionamiento del tooltip. En el ejemplo a continuación, nuestras clases de columna ya tienen esto, pero tu proyecto puede requerir una configuración alternativa.

¡Se ve bien!
¡Se ve bien!
@
Por favor elige un nombre de usuario único y válido.
Por favor proporciona una ciudad válida.
Por favor selecciona un estado válido.
Por favor proporciona un código postal válido.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip01" class="form-label">Nombre</label>
    <input type="text" class="form-control" id="validationTooltip01" value="Mark" required>
    <div class="valid-tooltip">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip02" class="form-label">Apellido</label>
    <input type="text" class="form-control" id="validationTooltip02" value="Otto" required>
    <div class="valid-tooltip">
      ¡Se ve bien!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltipUsername" class="form-label">Nombre de usuario</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">
        Por favor elige un nombre de usuario único y válido.
      </div>
    </div>
  </div>
  <div class="col-md-6 position-relative">
    <label for="validationTooltip03" class="form-label">Ciudad</label>
    <input type="text" class="form-control" id="validationTooltip03" required>
    <div class="invalid-tooltip">
      Por favor proporciona una ciudad válida.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip04" class="form-label">Estado</label>
    <select class="form-select" id="validationTooltip04" required>
      <option selected disabled value="">Elige...</option>
      <option>...</option>
    </select>
    <div class="invalid-tooltip">
      Por favor selecciona un estado válido.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip05" class="form-label">Código postal</label>
    <input type="text" class="form-control" id="validationTooltip05" required>
    <div class="invalid-tooltip">
      Por favor proporciona un código postal válido.
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Enviar formulario</button>
  </div>
</form>

CSS

Variables

Agregado en v5.3.0

Como parte del enfoque en evolución de las variables CSS de Bootstrap, los formularios ahora utilizan variables CSS locales para la validación para una personalización mejorada en tiempo real. Los valores para las variables CSS se establecen a través de Sass, por lo que la personalización con Sass también sigue siendo compatible.

--#{$prefix}form-valid-color: #{$form-valid-color};
--#{$prefix}form-valid-border-color: #{$form-valid-border-color};
--#{$prefix}form-invalid-color: #{$form-invalid-color};
--#{$prefix}form-invalid-border-color: #{$form-invalid-border-color};

Estas variables también se adaptan al modo de color, lo que significa que cambian de color mientras están en modo oscuro.

Variables 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.1'/></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>");
$form-valid-color:                  $form-feedback-valid-color;
$form-valid-border-color:           $form-feedback-valid-color;
$form-invalid-color:                $form-feedback-invalid-color;
$form-invalid-border-color:         $form-feedback-invalid-color;
$form-valid-color-dark:             $green-300;
$form-valid-border-color-dark:      $green-300;
$form-invalid-color-dark:           $red-300;
$form-invalid-border-color-dark:    $red-300;

Mixins Sass

Se combinan dos mixins, a través de nuestro bucle (loop), para generar nuestros estilos de respuesta de validación de formularios.

@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),
  $border-color: $color
) {
  .#{$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: $border-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: $border-color;
        @if $enable-shadows {
          @include box-shadow($input-box-shadow, $focus-box-shadow);
        } @else {
          // Avoid using mixin so we can pass custom focus shadow properly
          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: $border-color;

      @if $enable-validation-icons {
        &:not([multiple]):not([size]),
        &:not([multiple])[size="1"] {
          --#{$prefix}form-select-bg-icon: #{escape-svg($icon)};
          padding-right: $form-select-feedback-icon-padding-end;
          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: $border-color;
        @if $enable-shadows {
          @include box-shadow($form-select-box-shadow, $focus-box-shadow);
        } @else {
          // Avoid using mixin so we can pass custom focus shadow properly
          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: $border-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;
        }
      }
    }
  }
}

Mapas Sass

Este es el mapa Sass de validación de _variables.scss. Sobrescribe o extiende esto para generar estados diferentes o adicionales.

$form-validation-states: (
  "valid": (
    "color": var(--#{$prefix}form-valid-color),
    "icon": $form-feedback-icon-valid,
    "tooltip-color": #fff,
    "tooltip-bg-color": var(--#{$prefix}success),
    "focus-box-shadow": 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}success-rgb), $input-btn-focus-color-opacity),
    "border-color": var(--#{$prefix}form-valid-border-color),
  ),
  "invalid": (
    "color": var(--#{$prefix}form-invalid-color),
    "icon": $form-feedback-icon-invalid,
    "tooltip-color": #fff,
    "tooltip-bg-color": var(--#{$prefix}danger),
    "focus-box-shadow": 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}danger-rgb), $input-btn-focus-color-opacity),
    "border-color": var(--#{$prefix}form-invalid-border-color),
  )
);

Los mapas de $form-validation-states pueden contener tres parámetros opcionales para sobrescribir los tooltips y los estilos de enfoque.

Bucles Sass (Sass loops)

Se utiliza para iterar sobre los valores del mapa $form-validation-states para generar nuestros estilos de validación. Cualquier modificación al mapa Sass anterior se reflejará en tu CSS compilado a través de este bucle.

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

Personalización

Los estados de validación se pueden personalizar a través de Sass con el mapa $form-validation-states. Ubicado en nuestro archivo _variables.scss, este mapa Sass es cómo generamos los estados de validación predeterminados valid/invalid. Se incluye un mapa anidado para personalizar el color de cada estado, el icono, el color del tooltip y la sombra de enfoque. Si bien los navegadores no admiten otros estados, aquellos que usan estilos personalizados pueden agregar fácilmente comentarios de formulario más complejos.