Estados de validación y clases básicas
Bootstrap proporciona un sistema integral de validación que permite mostrar retroalimentación visual clara sobre el estado de los datos ingresados en formularios. Este sistema se basa en dos clases fundamentales que transforman la apariencia de los elementos de formulario para comunicar instantáneamente si los datos son correctos o requieren corrección.
Las clases de estado principales son .is-valid
y .is-invalid
, que se aplican directamente a los elementos de formulario para indicar visualmente su estado de validación. Cuando aplicamos .is-valid
a un input, el elemento adopta un borde verde y un color que sugiere éxito, mientras que .is-invalid
aplica un borde rojo que indica error o información faltante.
<input type="email" class="form-control is-valid" value="usuario@ejemplo.com">
<input type="password" class="form-control is-invalid" value="123">
Estas clases funcionan como modificadores visuales que se superponen al estilo base de los elementos de formulario. No alteran la funcionalidad del elemento, sino únicamente su presentación visual. Un input con .form-control
mantiene todas sus características básicas, pero la adición de .is-valid
o .is-invalid
modifica su apariencia para comunicar el estado de validación.
La aplicación de estados es directa y flexible. Podemos agregar estas clases a cualquier elemento de formulario en cualquier momento, ya sea desde el HTML inicial o mediante JavaScript posteriormente. El sistema está diseñado para ser agnóstico respecto al método de validación utilizado, funcionando igualmente bien con validación HTML5 nativa, librerías de JavaScript, o validación del lado del servidor.
<!-- Estado válido en diferentes elementos -->
<input type="text" class="form-control is-valid" value="Contenido correcto">
<select class="form-select is-valid">
<option selected>Opción válida</option>
</select>
<textarea class="form-control is-valid">Texto aprobado</textarea>
<!-- Estado inválido en diferentes elementos -->
<input type="email" class="form-control is-invalid" value="email-malformado">
<select class="form-select is-invalid">
<option>Seleccione una opción</option>
</select>
Impacto visual en elementos asociados
Los estados de validación no solo afectan al elemento de formulario principal, sino que también influyen en elementos relacionados como labels y componentes de input groups. Cuando aplicamos .is-valid
o .is-invalid
a un input dentro de un .input-group
, todo el grupo visual adopta el estilo correspondiente, creando una experiencia coherente.
<div class="input-group">
<span class="input-group-text">@</span>
<input type="text" class="form-control is-invalid" placeholder="Usuario">
</div>
Los labels asociados también responden visualmente a los estados de validación. Cuando un input tiene la clase .is-invalid
, su label correspondiente adopta automáticamente el color de error, creando una conexión visual clara entre el campo y su descripción.
<label for="emailInput" class="form-label">Correo electrónico</label>
<input type="email" class="form-control is-invalid" id="emailInput" value="correo-incorrecto">
Consistencia del sistema de estados
El diseño coherente es una característica fundamental del sistema de validación de Bootstrap. Independientemente del tipo de elemento de formulario, las clases .is-valid
e .is-invalid
aplican una paleta de colores consistente: verde para estados válidos y rojo para estados inválidos. Esta consistencia ayuda a los usuarios a reconocer inmediatamente el significado de los colores en cualquier contexto del formulario.
La herencia visual también se aplica a elementos complejos como checkboxes, radios y switches. Estos elementos mantienen su funcionalidad básica mientras adoptan los colores de estado apropiados, asegurando que toda la interfaz del formulario hable el mismo lenguaje visual.
<div class="form-check">
<input class="form-check-input is-invalid" type="checkbox" id="términos">
<label class="form-check-label" for="términos">
Acepto los términos y condiciones
</label>
</div>
<div class="form-check">
<input class="form-check-input is-valid" type="radio" name="opción" id="opción1">
<label class="form-check-label" for="opción1">
Opción seleccionada correctamente
</label>
</div>
La flexibilidad del sistema permite aplicar estos estados en cualquier momento del ciclo de vida del formulario. Podemos establecer estados iniciales, cambiarlos dinámicamente según la interacción del usuario, o aplicarlos como resultado de validaciones del servidor. Las clases funcionan como un interruptor visual que puede activarse y desactivarse según las necesidades de la aplicación.
Mensajes de feedback y retroalimentación
Bootstrap complementa los estados visuales de validación con un sistema de mensajes textuales que proporciona información específica sobre los errores o confirmaciones. Las clases .valid-feedback
y .invalid-feedback
permiten mostrar explicaciones claras que guían al usuario sobre qué corregir o confirman que los datos son correctos.
Estructura básica de mensajes
Los mensajes de feedback se implementan mediante elementos hermanos del control de formulario que contienen el texto explicativo. Estos elementos deben ubicarse inmediatamente después del input correspondiente para mantener la relación semántica y visual correcta.
<label for="emailInput" class="form-label">Correo electrónico</label>
<input type="email" class="form-control is-invalid" id="emailInput" value="usuario@">
<div class="invalid-feedback">
Por favor, introduce un correo electrónico válido.
</div>
La sincronización visual es automática: los mensajes con .invalid-feedback
solo son visibles cuando su elemento de formulario asociado tiene la clase .is-invalid
. De igual manera, .valid-feedback
solo aparece cuando el elemento tiene .is-valid
. Esta relación garantiza que solo se muestre el mensaje apropiado para el estado actual del campo.
<label for="passwordInput" class="form-label">Contraseña</label>
<input type="password" class="form-control is-valid" id="passwordInput" value="MiContraseña123!">
<div class="valid-feedback">
¡Contraseña segura confirmada!
</div>
<div class="invalid-feedback">
La contraseña debe tener al menos 8 caracteres, una mayúscula y un símbolo.
</div>
Mensajes informativos y útiles
Los mensajes efectivos deben ser específicos y orientados a la acción. En lugar de simplemente indicar que hay un error, deben explicar qué está mal y cómo corregirlo. Esto reduce la fricción del usuario y mejora significativamente la experiencia de completar formularios.
Ejemplo de formulario de registro:
<div class="mb-3">
<label for="username" class="form-label">Nombre de usuario</label>
<input type="text" class="form-control is-invalid" id="username" value="us">
<div class="invalid-feedback">
El nombre de usuario debe tener entre 3 y 20 caracteres.
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Correo electrónico</label>
<input type="email" class="form-control is-valid" id="email" value="usuario@empresa.com">
<div class="valid-feedback">
Correo verificado y disponible.
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Teléfono</label>
<input type="tel" class="form-control is-invalid" id="phone" value="123">
<div class="invalid-feedback">
Introduce un número de teléfono válido (ej: +34 612 345 678).
</div>
</div>
Feedback en formularios de contacto
Los formularios de contacto se benefician especialmente de mensajes claros que ayuden a los usuarios a proporcionar la información necesaria correctamente. Los mensajes deben ser amigables y profesionales, manteniendo el tono apropiado para la comunicación empresarial.
<form class="needs-validation" novalidate>
<div class="mb-3">
<label for="nombreCompleto" class="form-label">Nombre completo *</label>
<input type="text" class="form-control is-invalid" id="nombreCompleto" required>
<div class="invalid-feedback">
Este campo es obligatorio para procesar tu consulta.
</div>
</div>
<div class="mb-3">
<label for="empresa" class="form-label">Empresa</label>
<input type="text" class="form-control is-valid" id="empresa" value="Tech Solutions S.L.">
<div class="valid-feedback">
Información registrada correctamente.
</div>
</div>
<div class="mb-3">
<label for="mensaje" class="form-label">Mensaje *</label>
<textarea class="form-control is-invalid" id="mensaje" rows="4" required></textarea>
<div class="invalid-feedback">
Por favor, describe tu consulta para poder ayudarte mejor.
</div>
</div>
</form>
Mensajes en contextos de pago
Los formularios de pago requieren mensajes de validación especialmente claros debido a la sensibilidad de los datos financieros. Los mensajes deben transmitir confianza mientras guían al usuario para completar la información correctamente.
<div class="row">
<div class="col-md-8 mb-3">
<label for="cardNumber" class="form-label">Número de tarjeta</label>
<input type="text" class="form-control is-invalid" id="cardNumber" value="1234-5678-9012">
<div class="invalid-feedback">
El número de tarjeta debe tener 16 dígitos.
</div>
</div>
<div class="col-md-4 mb-3">
<label for="cvv" class="form-label">CVV</label>
<input type="text" class="form-control is-valid" id="cvv" value="123">
<div class="valid-feedback">
Código verificado.
</div>
</div>
</div>
<div class="mb-3">
<label for="cardName" class="form-label">Nombre del titular</label>
<input type="text" class="form-control is-valid" id="cardName" value="Juan Pérez García">
<div class="valid-feedback">
Nombre confirmado según los datos de la tarjeta.
</div>
</div>
Personalización de mensajes
Los mensajes pueden personalizarse para adaptarse a diferentes contextos y tonos de comunicación. Podemos utilizar las utilidades de color y tipografía de Bootstrap para enfatizar ciertos aspectos o mantener coherencia con la identidad visual de la aplicación.
<div class="mb-3">
<label for="edad" class="form-label">Edad</label>
<input type="number" class="form-control is-invalid" id="edad" value="16">
<div class="invalid-feedback">
<strong>Requisito de edad:</strong> Debes ser mayor de 18 años para registrarte.
</div>
</div>
<div class="mb-3">
<label for="codigo" class="form-label">Código promocional</label>
<input type="text" class="form-control is-valid" id="codigo" value="DESCUENTO2024">
<div class="valid-feedback">
<i class="bi bi-check-circle me-1"></i>
¡Código válido! Se aplicará un 20% de descuento.
</div>
</div>
Combinación con otros elementos
Los mensajes de feedback funcionan armónicamente con otros componentes de Bootstrap como alertas y badges para crear experiencias de validación más ricas. Esta integración permite mostrar información contextual adicional sin saturar la interfaz.
<div class="mb-3">
<label for="subscription" class="form-label">
Plan de suscripción
<span class="badge bg-primary">Recomendado</span>
</label>
<select class="form-select is-valid" id="subscription">
<option value="premium" selected>Plan Premium</option>
<option value="basic">Plan Básico</option>
</select>
<div class="valid-feedback">
Has seleccionado nuestro plan más popular con todas las funcionalidades.
</div>
</div>
La consistencia en el tono de los mensajes es fundamental para mantener una experiencia coherente. Los mensajes de error deben ser útiles sin ser intimidantes, mientras que los mensajes de éxito pueden ser más celebratorios para reforzar las acciones positivas del usuario.
Validación en diferentes tipos de controles
La aplicación de estados de validación se extiende uniformemente a todos los tipos de controles de formulario que hemos aprendido, manteniendo la consistencia visual mientras respeta las particularidades específicas de cada elemento. Cada tipo de control responde de manera apropiada a las clases .is-valid
e .is-invalid
, adaptando su apariencia según su naturaleza funcional.
Validación en inputs básicos
Los inputs de texto constituyen la base del sistema de validación y proporcionan el comportamiento más directo. Cada tipo de input (text, email, password, number) mantiene su funcionalidad específica mientras adopta los estados visuales correspondientes.
<!-- Formulario de registro con diferentes tipos de input -->
<div class="mb-3">
<label for="nombreUsuario" class="form-label">Nombre de usuario</label>
<input type="text" class="form-control is-valid" id="nombreUsuario" value="juan_developer">
<div class="valid-feedback">Nombre de usuario disponible.</div>
</div>
<div class="mb-3">
<label for="emailRegistro" class="form-label">Email</label>
<input type="email" class="form-control is-invalid" id="emailRegistro" value="email@incompleto">
<div class="invalid-feedback">El formato del email no es válido.</div>
</div>
<div class="mb-3">
<label for="passwordRegistro" class="form-label">Contraseña</label>
<input type="password" class="form-control is-invalid" id="passwordRegistro" value="123">
<div class="invalid-feedback">La contraseña debe tener al menos 8 caracteres.</div>
</div>
<div class="mb-3">
<label for="edadUsuario" class="form-label">Edad</label>
<input type="number" class="form-control is-valid" id="edadUsuario" value="25" min="18">
<div class="valid-feedback">Edad confirmada.</div>
</div>
Los textareas siguen el mismo patrón que los inputs básicos, aplicando los estados de validación de manera visualmente coherente. Son especialmente útiles para validar longitud de contenido o campos obligatorios de texto extenso.
<div class="mb-3">
<label for="descripcionPerfil" class="form-label">Descripción del perfil</label>
<textarea class="form-control is-invalid" id="descripcionPerfil" rows="4"></textarea>
<div class="invalid-feedback">La descripción es obligatoria (mínimo 50 caracteres).</div>
</div>
<div class="mb-3">
<label for="comentarios" class="form-label">Comentarios adicionales</label>
<textarea class="form-control is-valid" id="comentarios" rows="3">Excelente servicio, muy recomendable para futuros proyectos.</textarea>
<div class="valid-feedback">Comentario registrado correctamente.</div>
</div>
Validación en selectores
Los elementos select aplican estados de validación de forma natural, siendo especialmente útiles para validar selecciones obligatorias o verificar que el usuario ha elegido una opción válida del conjunto disponible.
<!-- Formulario de configuración con selectores -->
<div class="mb-3">
<label for="pais" class="form-label">País de residencia *</label>
<select class="form-select is-invalid" id="pais">
<option value="" selected>Selecciona tu país</option>
<option value="es">España</option>
<option value="mx">México</option>
<option value="ar">Argentina</option>
</select>
<div class="invalid-feedback">Debes seleccionar un país.</div>
</div>
<div class="mb-3">
<label for="categoria" class="form-label">Categoría profesional</label>
<select class="form-select is-valid" id="categoria">
<option value="">Seleccionar categoría</option>
<option value="dev" selected>Desarrollador</option>
<option value="design">Diseñador</option>
<option value="marketing">Marketing</option>
</select>
<div class="valid-feedback">Categoría seleccionada correctamente.</div>
</div>
<div class="mb-3">
<label for="habilidades" class="form-label">Habilidades principales</label>
<select class="form-select is-valid" id="habilidades" multiple>
<option value="js" selected>JavaScript</option>
<option value="css" selected>CSS</option>
<option value="html">HTML</option>
<option value="react">React</option>
</select>
<div class="valid-feedback">Se han seleccionado 2 habilidades.</div>
</div>
Validación en checkboxes, radios y switches
Los elementos de selección (checkboxes, radios y switches) requieren un enfoque particular para la validación, especialmente cuando se trata de campos obligatorios o grupos donde se debe seleccionar al menos una opción.
<!-- Validación de términos y condiciones -->
<div class="form-check mb-3">
<input class="form-check-input is-invalid" type="checkbox" id="aceptarTerminos">
<label class="form-check-label" for="aceptarTerminos">
Acepto los términos y condiciones de uso
</label>
<div class="invalid-feedback">
Debes aceptar los términos para continuar.
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input is-valid" type="checkbox" id="newsletter" checked>
<label class="form-check-label" for="newsletter">
Suscribirse al boletín de noticias
</label>
<div class="valid-feedback">
Te has suscrito correctamente.
</div>
</div>
<!-- Grupo de radios con validación -->
<fieldset class="mb-3">
<legend class="form-label">Método de contacto preferido *</legend>
<div class="form-check">
<input class="form-check-input is-invalid" type="radio" name="contacto" id="contactoEmail">
<label class="form-check-label" for="contactoEmail">Email</label>
</div>
<div class="form-check">
<input class="form-check-input is-invalid" type="radio" name="contacto" id="contactoTelefono">
<label class="form-check-label" for="contactoTelefono">Teléfono</label>
</div>
<div class="invalid-feedback d-block">
Selecciona al menos un método de contacto.
</div>
</fieldset>
<!-- Switch con validación -->
<div class="form-check form-switch mb-3">
<input class="form-check-input is-valid" type="checkbox" id="notificaciones" checked>
<label class="form-check-label" for="notificaciones">
Activar notificaciones push
</label>
<div class="valid-feedback">
Las notificaciones están activadas.
</div>
</div>
Validación en controles especiales
Los controles especiales como file inputs, range sliders, y selectores de fecha/color presentan desafíos únicos de validación que requieren atención a sus características específicas.
<!-- File input con validación -->
<div class="mb-3">
<label for="avatar" class="form-label">Foto de perfil</label>
<input class="form-control is-invalid" type="file" id="avatar" accept="image/*">
<div class="invalid-feedback">
Debes seleccionar una imagen válida (JPG, PNG, máximo 2MB).
</div>
</div>
<div class="mb-3">
<label for="documento" class="form-label">Documento de identidad</label>
<input class="form-control is-valid" type="file" id="documento" accept=".pdf,.jpg,.png">
<div class="valid-feedback">
Documento cargado correctamente.
</div>
</div>
<!-- Range slider con validación -->
<div class="mb-3">
<label for="experiencia" class="form-label">Años de experiencia: <span id="experienciaValor">2</span></label>
<input type="range" class="form-range is-invalid" id="experiencia" min="0" max="20" value="2">
<div class="invalid-feedback">
Se requiere mínimo 3 años de experiencia para esta posición.
</div>
</div>
<div class="mb-3">
<label for="presupuesto" class="form-label">Presupuesto: <span id="presupuestoValor">5000€</span></label>
<input type="range" class="form-range is-valid" id="presupuesto" min="1000" max="10000" step="500" value="5000">
<div class="valid-feedback">
Presupuesto dentro del rango aceptable.
</div>
</div>
<!-- Controles de fecha y color -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="fechaNacimiento" class="form-label">Fecha de nacimiento</label>
<input type="date" class="form-control is-valid" id="fechaNacimiento" value="1995-06-15">
<div class="valid-feedback">Fecha confirmada.</div>
</div>
<div class="col-md-6 mb-3">
<label for="colorFavorito" class="form-label">Color corporativo</label>
<input type="color" class="form-control form-control-color is-invalid" id="colorFavorito" value="#ff0000">
<div class="invalid-feedback">Selecciona un color que cumpla con las directrices de marca.</div>
</div>
</div>
Validación en grupos de inputs
Los input groups mantienen su cohesión visual cuando se aplican estados de validación, asegurando que todos los elementos del grupo (addons, botones, inputs) reflejen el estado apropiado de manera coordinada.
<!-- Input group con validación de URL -->
<div class="mb-3">
<label for="sitioWeb" class="form-label">Sitio web corporativo</label>
<div class="input-group has-validation">
<span class="input-group-text">https://</span>
<input type="text" class="form-control is-invalid" id="sitioWeb" value="mi-sitio">
<div class="invalid-feedback">
Introduce una URL válida (ej: www.empresa.com).
</div>
</div>
</div>
<!-- Input group con botón y validación -->
<div class="mb-3">
<label for="codigoPromocional" class="form-label">Código promocional</label>
<div class="input-group has-validation">
<input type="text" class="form-control is-valid" id="codigoPromocional" value="DESCUENTO2024">
<button class="btn btn-outline-success" type="button">Verificar</button>
<div class="valid-feedback">
Código válido. Descuento del 15% aplicado.
</div>
</div>
</div>
<!-- Input group con precio y validación -->
<div class="mb-3">
<label for="precio" class="form-label">Precio del producto</label>
<div class="input-group has-validation">
<span class="input-group-text">€</span>
<input type="number" class="form-control is-invalid" id="precio" value="0" min="1">
<span class="input-group-text">.00</span>
<div class="invalid-feedback">
El precio debe ser mayor que 0€.
</div>
</div>
</div>
Casos prácticos integrados
Un formulario de pago completo demuestra cómo diferentes tipos de controles trabajan juntos manteniendo la consistencia en los estados de validación:
<form class="row g-3">
<div class="col-md-6">
<label for="nombreTarjeta" class="form-label">Nombre en la tarjeta</label>
<input type="text" class="form-control is-valid" id="nombreTarjeta" value="Juan Pérez">
<div class="valid-feedback">Nombre confirmado.</div>
</div>
<div class="col-md-6">
<label for="tipoTarjeta" class="form-label">Tipo de tarjeta</label>
<select class="form-select is-valid" id="tipoTarjeta">
<option value="visa" selected>Visa</option>
<option value="mastercard">Mastercard</option>
</select>
<div class="valid-feedback">Tipo seleccionado.</div>
</div>
<div class="col-md-8">
<label for="numeroTarjeta" class="form-label">Número de tarjeta</label>
<input type="text" class="form-control is-invalid" id="numeroTarjeta" value="4532-1234-5678">
<div class="invalid-feedback">Número de tarjeta incompleto.</div>
</div>
<div class="col-md-4">
<label for="cvv" class="form-label">CVV</label>
<div class="input-group has-validation">
<input type="text" class="form-control is-valid" id="cvv" value="123">
<span class="input-group-text">
<i class="bi bi-question-circle" data-bs-toggle="tooltip" title="Código de 3 dígitos en el reverso"></i>
</span>
<div class="valid-feedback">CVV verificado.</div>
</div>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input is-invalid" type="checkbox" id="guardarTarjeta">
<label class="form-check-label" for="guardarTarjeta">
Guardar información de pago para futuras compras
</label>
<div class="invalid-feedback">
Debes aceptar las condiciones de seguridad para guardar la tarjeta.
</div>
</div>
</div>
</form>
La versatilidad del sistema de validación permite crear experiencias de usuario coherentes independientemente de la complejidad o diversidad de controles en el formulario. Cada elemento mantiene su funcionalidad específica mientras contribuye a una narrativa visual unificada que guía al usuario hacia la completación exitosa del formulario.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Bootstrap
Documentación oficial de Bootstrap
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Bootstrap es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Bootstrap
Explora más contenido relacionado con Bootstrap y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender las clases básicas de validación
.is-valid
y.is-invalid
para indicar estados de formulario. - Aprender a implementar mensajes de retroalimentación con
.valid-feedback
y.invalid-feedback
. - Aplicar validaciones visuales en diferentes tipos de controles como inputs, selects, checkboxes, radios y controles especiales.
- Integrar estados de validación en grupos de inputs y formularios complejos manteniendo coherencia visual.
- Personalizar mensajes de validación para mejorar la experiencia del usuario en distintos contextos.