1. ¿Qué es un Formulario?
Un formulario en HTML es una sección de un documento que contiene controles interactivos (campos de texto, botones, checkboxes, etc.) que permiten al usuario enviar información a un servidor web. Es la vía principal de comunicación bidireccional en la web: desde un simple buscador hasta complejos sistemas de registro, compras online o configuración de perfiles.
La etiqueta contenedora es <form>, y dentro de ella colocaremos todos los elementos
necesarios para recoger los datos.
2. La Etiqueta <form> y sus Atributos
El comportamiento del formulario se define mediante sus atributos en la etiqueta de apertura.
Atributos Principales
| Atributo | Descripción |
|---|---|
action |
Define la URL (dirección) a la que se envían los datos cuando el usuario envía el formulario. Si se omite, se envían a la misma página. |
method |
Especifica el método HTTP usado para enviar los datos.
|
enctype |
Define cómo se codifican los datos antes de enviarlos (solo con method="POST").
|
autocomplete |
on (por defecto) o off. Permite al navegador sugerir
autocompletado basado en entradas previas. |
novalidate |
Si está presente, el navegador no validará los datos automáticamente antes de enviarlos. |
target |
Dónde mostrar la respuesta: _blank (nueva pestaña), _self (misma
pestaña, por defecto). |
<!-- Ejemplo de formulario de registro seguro -->
<form action="registro.php" method="POST" autocomplete="on">
... campos del formulario ...
</form>
<!-- Ejemplo de formulario de búsqueda -->
<form action="buscar.html" method="GET">
... campo de búsqueda ...
</form>
3. La Importancia de las Etiquetas (Labels)
La etiqueta <label> define un rótulo para un elemento de formulario. Su uso es
fundamental por dos razones:
- Accesibilidad: Los lectores de pantalla leen el label cuando el usuario enfoca el input.
- Usabilidad: Al hacer clic en el texto del label, el foco se va automáticamente al input asociado (muy útil en checkboxes y radios pequeños).
Agrupación de Campos: Fieldset y Legend
Para mantener el formulario organizado, especialmente si es largo, usa <fieldset>
para agrupar campos relacionados.
La etiqueta <legend> define el título de ese grupo.
<fieldset>
<legend>Datos Personales</legend>
... inputs de nombre, edad ...
</fieldset>
Forma Explícita (Recomendada)
Usando el atributo for en el label que coincida exactamente con el id del
input.
<label for="nombre_usuario">Nombre de Usuario:</label>
<input type="text" id="nombre_usuario" name="username">
Forma Implícita
Envolviendo el input dentro del label.
<label>
Nombre de Usuario:
<input type="text" name="username">
</label>
4. ¡CRÍTICO! El Atributo name
A menudo los principiantes confunden id con name. Para el CSS y JS usamos
id,
pero para enviar datos al servidor el atributo name es OBLIGATORIO.
Si un input no tiene name, sus datos NO se enviarán. El servidor recibe
los datos en pares name=valor.
Manejo de Arrays con []
A veces necesitamos enviar múltiples valores para un mismo concepto, por ejemplo, en una lista de
opciones múltiple.
Para esto, añadimos corchetes vacíos [] al final del valor del atributo name.
El servidor interpretará esto como un array (lista) de valores en lugar de un valor
único.
Elige tus intereses (Checkbox múltiple):
<!-- El servidor recibirá un array: intereses = ["Deportes", "Música"] -->
<input type="checkbox" name="intereses[]" value="Deportes">
<input type="checkbox" name="intereses[]" value="Música">
<input type="checkbox" name="intereses[]" value="Cine">
5. Campos de Entrada (Input Types)
La etiqueta <input> es la navaja suiza de los formularios. Su comportamiento cambia
drásticamente según el atributo type.
5.1 Text y Variantes
Estos campos recogen datos alfanuméricos. Aunque visualmente parecen iguales, el atributo
type
cambia cómo el navegador valida el dato y, sobre todo, qué teclado muestra en móviles.
<!-- Campos de texto variados -->
<input type="text" name="texto" placeholder="Texto normal">
<input type="password" name="password" placeholder="••••••">
<input type="email" name="email" placeholder="nombre@mail.com">
<input type="tel" name="telefono" placeholder="600 123 456">
<input type="url" name="url" placeholder="https://miweb.com">
<input type="search" name="busqueda" placeholder="Buscar...">
5.2 Numéricos
Optimizados para cifras. En móviles muestran el teclado numérico.
number incluye "flechitas" (spinners) para subir/bajar valor.
range muestra un control deslizante visual, ideal cuando el valor exacto no es crítico.
<input type="number" name="numero" min="0" max="100" step="5">
<!-- Range con visualización de valor -->
<input type="range" name="rango" min="0" max="100" value="50"
oninput="this.nextElementSibling.value = this.value">
<output>50</output>
5.3 Fecha y Hora
Despliegan los calendarios y selectores de hora nativos del dispositivo. Simplifican enormemente la introducción de fechas sin necesidad de librerías extrañas.
date: Fecha completa (día, mes, año).month: Selecciona mes y año.week: Selecciona semana y año.time: Hora y minutos (a veces segundos).datetime-local: Fecha y hora (sin zona horaria).
<!-- Selectores de Fecha y Hora -->
<input type="date" name="fecha">
<input type="time" name="hora">
<input type="datetime-local" name="fecha_hora">
<input type="month" name="mes">
<input type="week" name="semana">
5.4 Especiales: Color, Archivo y Oculto
- Color: Abre el selector de color del sistema operativo.
-
File: Permite subir archivos. El atributo
acceptfiltra qué archivos se pueden elegir:- Extensiones:
accept=".jpg, .pdf" - Tipos MIME (recomendado):
accept="image/*"(cualquier imagen),accept="audio/*"
- Extensiones:
- Hidden: Datos invisibles.
Truco Anti-Spam (Honeypot): Puedes poner un campo hidden (o oculto por CSS) que los bots rellenan automáticamente. Si al recibir el formulario en el servidor ese campo tiene datos, ¡es un bot! (Los humanos no lo ven).
<input type="color" name="color">
<input type="file" name="archivo" accept="image/*">
<input type="hidden" name="id_usuario" value="99">
6. Textarea (Texto Multilínea)
Para textos largos como comentarios o biografías, usamos <textarea>.
A diferencia de input, este elemento tiene etiqueta de cierre y el texto inicial va entre
ellas.
Permite escribir en múltiples líneas. Por defecto el usuario puede cambiar su tamaño arrastrando la
esquina,
pero podemos evitarlo con CSS (resize: none;) si rompe nuestro diseño.
<textarea name="bio" rows="4"></textarea>
7. Elementos de Selección
7.1 Select (Menú Desplegable)
Muestra una lista de opciones. Es ideal para ahorrar espacio.
Podemos agrupar opciones con <optgroup>.
Selección Múltiple: Añadiendo el atributo multiple, el usuario puede
elegir varias opciones (manteniendo pulsado Ctrl o Shift).
⚠️ IMPORTANTE: Si es múltiple, el nombre debe llevar corchetes name="paises[]" para
enviar un array al servidor.
Nota: Con JS podemos validar que se seleccionen un mínimo o máximo de opciones.
Para marcar una opción por defecto, añade el atributo selected a la etiqueta
<option> deseada.
<select name="pais">
<option value="" disabled>-- Elige --</option>
<option value="es" selected>España</option>
<option value="mx">México</option>
<optgroup label="Otros">
<option value="us">USA</option>
</optgroup>
</select>
7.2 Radio Buttons (Opción única)
Se usan cuando el usuario debe elegir una sola opción entre varias (ej: Género, Método
de pago).
Al contrario que el select, aquí todas las opciones están visibles.
Importante: Para que funcionen como grupo, deben compartir el exacto mismo valor en
el atributo name.
Usa el atributo checked para marcar una opción por defecto.
Género:
<!-- Radio buttons: Mismo NAME para ser grupo -->
<input type="radio" id="g_mujer" name="genero" value="mujer checked">
<label for="g_mujer">Mujer</label>
<input type="radio" id="g_hombre" name="genero" value="hombre">
<label for="g_hombre">Hombre</label>
<input type="radio" id="g_otro" name="genero" value="otro">
<label for="g_otro">Otro</label>
7.3 Checkboxes (Opción múltiple)
Casillas de verificación independientes. El usuario puede marcar todas, algunas o
ninguna.
Ideales para aceptar términos, elegir ingredientes extra, o configuraciones on/off.
También aceptan el atributo checked para aparecer marcadas inicialmente.
<input type="checkbox" id="c_terminos" name="terminos" required>
<label for="c_terminos">Acepto los términos...</label>
Elemento Datalist (Autocompletado)
Proporciona una lista de opciones predefinidas para un <input>.
A diferencia del <select>, aquí el usuario puede seleccionar una opción sugerida
o escribir algo totalmente nuevo.
<input list="navegadores">
<datalist id="navegadores">
<option value="Chrome">
<option value="Firefox">
...
</datalist>
8. Botones
Hay varias formas de crear botones. La recomendada en formularios clásicos es usar
<input>.
| Código | Función |
|---|---|
<input type="submit" value="Enviar"> |
Envía el formulario (Acción por defecto). |
<input type="reset" value="Borrar"> |
Restablece todos los campos a sus valores iniciales. |
<input type="button" value="Botón"> |
Botón "tonto". No hace nada por sí mismo. Se usa con JavaScript. |
<button>Enviar</button> |
Más flexible (permite iconos o HTML dentro). Por defecto actúa como submit. |
<!-- Diferentes formas de hacer botones -->
<input type="submit" value="Enviar Datos" class="btn btn_primary">
<input type="reset" value="Limpiar" class="btn btn_secondary">
<input type="button" value="Click JS" class="btn btn_danger">
Atributos Globales de Validación
Permiten validar datos en el cliente (navegador) antes de enviar.
| Atributo | Descripción |
|---|---|
required |
Obliga a que el campo no esté vacío. |
readonly |
El usuario ve el valor pero no puede editarlo (sí se envía). |
disabled |
El campo no es editable y NO se envía al servidor. |
placeholder |
Texto fantasma de ayuda (desaparece al escribir). |
pattern |
Validación avanzada con Expresiones Regulares (Regex). |
min / max |
Valores límite para números y fechas. |
step |
Incrementos permitidos (ej. 0.01 para precio). |
autofocus |
Pone el cursor en este campo al cargar la página. |
Las Limitaciones de Validar solo con HTML5
Aunque los atributos como required, type="email" o pattern son
muy útiles para una primera capa de seguridad
y mejoran la experiencia de usuario (UX), NO son infalibles ni suficientes para una
aplicación profesional.
Aquí te explicamos por qué:
1. Validaciones "Laxas" (Poco estrictas)
Los estándares de HTML5 son a veces demasiado flexibles.
- Email: Un input
type="email"considera válidousuario@dominio(sin extensión .com, .es, etc.). Esto es técnicamente válido según el estándar RFC, pero casi nunca es lo que queremos en una web real.¿Qué es un RFC?
Los RFC (Request for Comments) son documentos que describen la "ingeniería" de servicios, protocolos y estándares para internet. Definen cómo "algo" en internet debería comportarse en un escenario dado, crean directrices para el uso y la seguridad.
- URL: Valida el formato y protocolo, pero no comprueba que el dominio exista realmente o que la web esté activa.
2. Mensajes de Error Genéricos
Cada navegador muestra sus propios mensajes ("Complete este campo", "Please fill out this field") y tienen estilos difíciles de personalizar. Con JavaScript, puedes mostrar mensajes exactos y diseñados a medida.
3. Falta de Lógica Compleja
HTML5 no puede validar cosas que dependen de otros campos o lógica externa:
- "Confirmar contraseña" debe ser igual a "Contraseña".
- "Fecha de vuelta" debe ser posterior a "Fecha de ida".
- Comprobar si un nombre de usuario ya existe en la base de datos (esto requiere AJAX/JS).
Accesibilidad y Tabindex
El atributo tabindex controla el orden de navegación con la tecla Tab.
Es una herramienta potente pero peligrosa.
tabindex="0": Incluye un elemento no interactivo (div, span) en el flujo natural de tabulación.tabindex="-1": Saca el elemento del flujo de teclado (pero permite foco vía JS). Útil para modales.tabindex="1+"(Positivo): EVITAR. Altera el orden natural y rompe la accesibilidad si la estructura cambia.
Ejemplo de Estructura Ideal
<form action="/procesar" method="POST">
<fieldset>
<legend>Información Personal</legend>
<label for="nombre">Nombre Completo:</label>
<input type="text" id="nombre" name="user_name" required placeholder="Ej: Juan Pérez">
<label for="correo">Email:</label>
<input type="email" id="correo" name="user_email" required>
</fieldset>
<fieldset>
<legend>Preferencias</legend>
<label>
<input type="radio" name="genero" value="h"> Hombre
</label>
<label>
<input type="radio" name="genero" value="m"> Mujer
</label>
</fieldset>
<button type="submit">Enviar Registro</button>
</form>
10. Estilizando Formularios
Los formularios por defecto se ven diferentes en cada navegador y sistema operativo. Aprender a estilizarlos con CSS es vital para una buena experiencia de usuario.
Hemos preparado una guía completa y una tarjeta de referencia en la sección de CSS:
CSSAprende a quitar el estilo por defecto, crear inputs modernos, estados focus y botones atractivos.
Ir a la Guía de Estilos🎮 ChorimaForms (Diseñador de Formularios)
Ahora que conoces todos los elementos de formularios, es momento de practicar de forma visual. El Diseñador de Formularios de Blackchorima te permite diseñar formularios profesionales con drag & drop, sin escribir código.
- ✅ Experimentar con todos los tipos de campos (text, email, date, select, etc.)
- ✅ Aprender la estructura HTML de formularios complejos
- ✅ Practicar estilización con CSS en tiempo real
- ✅ Generar código HTML limpio para tus proyectos
- ✅ Crear layouts avanzados con Grid y Flexbox
Diseña formularios visualmente con drag & drop
Empezar a Diseñar 📚 TutorialAprende a usar todas las características paso a paso
Ver Tutorial💡 Tip: Usa el Diseñador de Formularios para los ejercicios de formularios y exporta el HTML generado