En esta página

Validación de formularios con HTML5

12 min lectura TextoCap. 4 — Formularios

Validación nativa del navegador

HTML5 introdujo un sistema de validación integrado en el navegador que funciona sin JavaScript. Cuando un usuario intenta enviar un formulario con datos invalidos, el navegador muestra mensajes de error automaticos y bloquea el envio.

Esta validación nativa tiene varias ventajas:

  • Funciona inmediatamente sin código adicional
  • Los mensajes estan traducidos al idioma del usuario
  • Es accesible para lectores de pantalla
  • Proporciona feedback visual con pseudoclases CSS

Atributos de validación

required

El atributo más básico. Indica que el campo es obligatorio y no puede quedar vacio:

<label for="nombre">Nombre *</label>
<input type="text" id="nombre" name="nombre" required>

Si el usuario intenta enviar el formulario sin completar este campo, el navegador mostrara un mensaje como "Por favor, rellena este campo".

minlength y maxlength

Controlan la longitud del texto permitido:

<label for="bio">Biografia</label>
<textarea id="bio" name="bio"
  minlength="10"
  maxlength="500"
  placeholder="Minimo 10 caracteres, máximo 500"></textarea>

maxlength impide que el usuario escriba más caracteres de los permitidos. minlength muestra un error al enviar si el texto es demasiado corto.

min, max y step

Para campos numericos y de fecha:

<!-- Número entre 1 y 100, de 5 en 5 -->
<input type="number" name="cantidad" min="1" max="100" step="5">

<!-- Fecha mínima y máxima -->
<input type="date" name="fecha" min="2025-01-01" max="2025-12-31">

<!-- Numeros decimales con step -->
<input type="number" name="precio" min="0" max="9999.99" step="0.01">

El atributo step define el incremento válido. Con step="0.01" permites dos decimales.

pattern

Permite definir una expresión regular que el valor debe cumplir:

<!-- Solo letras y espacios -->
<input type="text" name="nombre" pattern="[a-zA-ZáéíóúñÁÉÍÓÚÑ\s]+"
  title="Solo se permiten letras y espacios">

<!-- Código postal boliviano (4 digitos) -->
<input type="text" name="cp" pattern="\d{4}"
  title="Ingresa un código postal de 4 digitos">

<!-- Telefono con formato -->
<input type="tel" name="telefono" pattern="\+?[0-9\s\-]{7,15}"
  title="Formato válido: +591 70012345">

El atributo title es importante: su contenido se muestra como parte del mensaje de error cuando el patrón no coincide.

type como validador

Los tipos de input de HTML5 ya incluyen validación automática:

Tipo Validación automática
email Verifica formato de correo (debe incluir @)
url Verifica formato de URL (debe incluir protocolo)
number Solo acepta números
date Solo acepta fechas validas
tel No válida formato (varia por pais), pero muestra teclado numérico en móvil

El atributo title para mensajes personalizados

El atributo title se combina con pattern para proporcionar mensajes de error descriptivos:

<input type="text" name="usuario"
  pattern="[a-zA-Z0-9_]{3,20}"
  title="Nombre de usuario: 3-20 caracteres, solo letras, números y guion bajo">

Sin title, el navegador solo mostrara un mensaje genérico como "Incluir un valor en el formato solicitado". Con title, el usuario recibe instrucciones claras sobre que se espera.

Pseudoclases CSS de validación

CSS proporciona pseudoclases que se aplican segun el estado de validación del campo:

/* Campo válido */
input:valid {
  border-color: green;
}

/* Campo invalido */
input:invalid {
  border-color: red;
}

/* Campo obligatorio */
input:required {
  border-left: 3px solid orange;
}

/* Campo opcional */
input:optional {
  border-left: 3px solid gray;
}

/* Campo dentro del rango (min/max) */
input:in-range {
  background-color: #e8f5e9;
}

/* Campo fuera del rango */
input:out-of-range {
  background-color: #ffebee;
}

Evitar estilos prematuros

Un problema comun es que :invalid se aplica incluso antes de que el usuario interactue con el campo. Para evitarlo, puedes combinar pseudoclases:

/* Solo mostrar error despues de interactuar */
input:not(:placeholder-shown):invalid {
  border-color: red;
}

/* O usar :user-invalid (soporte moderno) */
input:user-invalid {
  border-color: red;
}

La pseudoclase :user-invalid es más reciente y solo se activa despues de que el usuario interactua con el campo.

Desactivar la validación nativa

En algunos casos (por ejemplo, cuando usas validación con JavaScript), puedes desactivar la validación nativa:

<!-- Desactivar en todo el formulario -->
<form action="/enviar" method="post" novalidate>
  <!-- Los campos siguen teniendo atributos de validación,
       pero el navegador no los verifica al enviar -->
</form>

<!-- Desactivar solo en el boton de envio -->
<button type="submit" formnovalidate>Guardar borrador</button>

Esto es útil para botones de "guardar borrador" que no requieren todos los campos completos.

Ejemplo completo: formulario con validación

<form action="/contacto" method="post">
  <label for="nombre">Nombre completo *</label>
  <input type="text" id="nombre" name="nombre"
    required minlength="2" maxlength="100">

  <label for="email">Email *</label>
  <input type="email" id="email" name="email" required>

  <label for="asunto">Asunto *</label>
  <select id="asunto" name="asunto" required>
    <option value="">Elige un asunto</option>
    <option value="soporte">Soporte técnico</option>
    <option value="ventas">Ventas</option>
    <option value="otro">Otro</option>
  </select>

  <label for="mensaje">Mensaje *</label>
  <textarea id="mensaje" name="mensaje"
    required minlength="20" maxlength="2000"
    rows="6"></textarea>

  <button type="submit">Enviar mensaje</button>
</form>

Este formulario no necesita una sola linea de JavaScript para validar que los campos estan completos, que el email tiene formato correcto y que el mensaje tiene una longitud mínima.

Práctica

  1. Anade validación a un formulario existente: Toma un formulario que ya tengas y agrega required, minlength, maxlength, min, max y pattern a los campos correspondientes. Verifica que el navegador bloquea el envio con datos invalidos.
  2. Crea un campo con pattern personalizado: Construye un campo que solo acepte un código postal de tu pais usando pattern y proporciona un mensaje claro con el atributo title.
  3. Estiliza con pseudoclases de validación: Escribe reglas CSS usando :valid, :invalid, :required y :out-of-range para dar feedback visual a los campos del formulario.

En la siguiente leccion aprenderemos sobre meta tags y como optimizar nuestras páginas para motores de busqueda.

Validación del servidor es obligatoria
La validación de HTML5 solo funciona en el navegador y puede ser desactivada facilmente. SIEMPRE válida los datos en el servidor también. La validación del cliente es una mejora de experiencia, no una medida de seguridad.
Pseudoclases CSS de validación
CSS ofrece pseudoclases como :valid, :invalid, :required y :placeholder-shown que permiten estilizar campos segun su estado de validación, sin necesidad de JavaScript.
html
<form action="/registro" method="post" id="form-registro">
  <div>
    <label for="usuario">Nombre de usuario *</label>
    <input type="text" id="usuario" name="usuario"
      required
      minlength="3"
      maxlength="20"
      pattern="[a-zA-Z0-9_]+"
      title="Solo letras, números y guion bajo. Entre 3 y 20 caracteres."
      autocomplete="username">
  </div>

  <div>
    <label for="email">Correo electronico *</label>
    <input type="email" id="email" name="email"
      required
      placeholder="[email protected]"
      autocomplete="email">
  </div>

  <div>
    <label for="edad">Edad *</label>
    <input type="number" id="edad" name="edad"
      required
      min="13"
      max="120"
      step="1">
  </div>

  <div>
    <label for="sitio-web">Sitio web (opcional)</label>
    <input type="url" id="sitio-web" name="sitioWeb"
      placeholder="https://tusitio.com">
  </div>

  <div>
    <label for="password">Contrasena *</label>
    <input type="password" id="password" name="password"
      required
      minlength="8"
      pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
      title="Minimo 8 caracteres con al menos una mayuscula, una minuscula y un número."
      autocomplete="new-password">
  </div>

  <button type="submit">Registrarse</button>
</form>