Formularios

Crea formularios HTML accesibles y funcionales: inputs, selects, checkboxes, radios, validación nativa y buenas prácticas.

Los formularios son el principal mecanismo de interacción entre el usuario y una web: login, registro, búsqueda, checkout, contacto… Todos son formularios. Hacerlos bien desde el HTML marca la diferencia en accesibilidad y UX.


Estructura básica de un formulario

<form action="/enviar" method="POST">
  <label for="nombre">Nombre completo</label>
  <input type="text" id="nombre" name="nombre" />

  <button type="submit">Enviar</button>
</form>
  • actionURL a donde se envían los datos
  • methodGET (datos en la URL) o POST (datos en el cuerpo)
  • name → nombre del campo que llega al servidor

La etiqueta <label>

El <label> no es opcional — es fundamental para la accesibilidad. Asocia un texto descriptivo a su campo:

<!-- ✅ Asociado con 'for' + 'id' -->
<label for="email">Correo electrónico</label>
<input type="email" id="email" name="email" />

<!-- ✅ Envolviendo el input (también válido) -->
<label>
  Correo electrónico
  <input type="email" name="email" />
</label>

Con <label> correctamente asociado, al clicar el texto también se activa el campo — mejor UX y accesibilidad para lectores de pantalla.


Tipos de <input>

El atributo type cambia completamente el comportamiento:

<input type="text"     name="nombre"    placeholder="Tu nombre" />
<input type="email"    name="email"     placeholder="tu@email.com" />
<input type="password" name="password"  placeholder="Contraseña" />
<input type="number"   name="edad"      min="0" max="120" />
<input type="tel"      name="telefono"  placeholder="+34 600 000 000" />
<input type="url"      name="web"       placeholder="https://" />
<input type="date"     name="fecha" />
<input type="time"     name="hora" />
<input type="color"    name="color" />
<input type="range"    name="volumen"   min="0" max="100" step="5" />
<input type="file"     name="archivo"   accept=".pdf,.jpg" />
<input type="hidden"   name="token"     value="abc123" />
<input type="checkbox" name="acepto"    id="acepto" />
<input type="radio"    name="sexo"      value="m" id="masculino" />
<input type="search"   name="q"         placeholder="Buscar..." />

El navegador adapta el teclado en móvil según el type (numérico para number, @ para email, etc.).


<textarea>

Para texto de varias líneas:

<label for="mensaje">Mensaje</label>
<textarea id="mensaje" name="mensaje" rows="5" cols="40" placeholder="Escribe aquí..."></textarea>

<select> y <option>

Desplegables de selección:

<label for="pais">País</label>
<select id="pais" name="pais">
  <option value="">Selecciona un país</option>
  <option value="es">España</option>
  <option value="mx">México</option>
  <option value="ar">Argentina</option>
</select>

<!-- Agrupación con optgroup -->
<select name="lenguaje">
  <optgroup label="Frontend">
    <option value="html">HTML</option>
    <option value="css">CSS</option>
  </optgroup>
  <optgroup label="Backend">
    <option value="node">Node.js</option>
    <option value="python">Python</option>
  </optgroup>
</select>

Validación nativa del navegador

HTML incluye validación sin JavaScript:

<form>
  <!-- required: campo obligatorio -->
  <input type="text" name="nombre" required />

  <!-- minlength / maxlength: longitud mínima y máxima -->
  <input type="text" name="usuario" minlength="3" maxlength="20" required />

  <!-- min / max para números y fechas -->
  <input type="number" name="edad" min="18" max="99" required />

  <!-- pattern: validación con regex -->
  <input
    type="text"
    name="codigo-postal"
    pattern="[0-9]{5}"
    title="Introduce 5 dígitos"
    required
  />

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

Fieldset y legend

Para agrupar campos relacionados:

<form>
  <fieldset>
    <legend>Datos personales</legend>
    <label for="nombre">Nombre</label>
    <input type="text" id="nombre" name="nombre" />

    <label for="apellido">Apellido</label>
    <input type="text" id="apellido" name="apellido" />
  </fieldset>

  <fieldset>
    <legend>Preferencias</legend>
    <label><input type="checkbox" name="newsletter" /> Recibir newsletter</label>
    <label><input type="checkbox" name="ofertas" /> Recibir ofertas</label>
  </fieldset>

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

En la última lección del curso vemos HTML5 semántico: las etiquetas que dan significado real a la estructura de la página.