Menu

Formularios en HTML: campos, action, method y validación

Cómo crear un formulario en HTML: el elemento form, los atributos name, action y method (GET frente a POST), agrupar campos con fieldset y legend, la validación integrada con required y pattern, y cómo gestionar el envío con JavaScript.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Cómo hacer un formulario en HTML

Un formulario es un elemento <form> que contiene campos y un botón de envío. Cada campo necesita un name: es la clave con la que se envía el valor. Rellena el formulario y pulsa Send. La vista previa no envía nada a ningún sitio; muestra exactamente lo que habría enviado el navegador.

Las piezas:

  • action es la URL a la que van los datos, y method es cómo (post aquí).
  • name en cada campo. Su valor es lo que escribió el lector.
  • <label> da nombre a cada campo en pantalla y para los lectores de pantalla (consulta label en HTML).
  • required y type="email" hacen que el navegador compruebe los campos antes de enviar. Prueba a enviar con el nombre vacío, o con abc como correo.
  • El botón de envío envía el formulario. Pulsar Enter en un campo de texto también.

action y method: a dónde y cómo van los datos

AtributoValoresPor defecto
actionCualquier URLLa URL de la página actual
methodget, post, dialogget
enctypeapplication/x-www-form-urlencoded, multipart/form-data, text/plainapplication/x-www-form-urlencoded

Con method="get", los campos se convierten en la cadena de consulta de la URL: un formulario de búsqueda con name="q" va a /search?q=blue+shoes. Es lo correcto para búsquedas y filtros, porque el resultado se puede guardar en marcadores y compartir. Con method="post", los campos van en el cuerpo de la petición y no aparecen en la barra de direcciones ni en el historial. Usa POST para todo lo que inicia sesión, crea, modifica o borra algo, y para las contraseñas.

Un formulario con subida de archivos (<input type="file">) necesita method="post" y enctype="multipart/form-data", o solo se envía el nombre del archivo. method="dialog" es para un formulario dentro de un <dialog>: al enviarlo se cierra el diálogo en lugar de hacer una petición.

Qué se envía

Solo se envían los campos con name, y solo cuando no están disabled. Pulsa Submit y compara los campos con lo que envía el formulario:

El formulario envía city, zip, source y action. El campo sin nombre, el campo deshabilitado y la casilla sin marcar se omiten. Los campos ocultos se envían pero nunca se muestran, y el botón de envío manda su propio name y value porque fue el botón que se usó.

Agrupar campos con fieldset y legend

<fieldset> dibuja una caja alrededor de campos relacionados, y <legend> es su título. Los lectores de pantalla anuncian la leyenda cuando el foco entra en el grupo, que es lo que hace comprensible un conjunto de botones de opción como los de abajo: "Delivery, Standard, botón de opción".

disabled en un fieldset deshabilita de una vez todos los campos que contiene, y ninguno se envía. Quítalo y los campos de regalo se pueden usar.

Validación integrada: required, pattern y compañía

Los navegadores comprueban estos atributos antes de enviar y muestran un mensaje en el primer campo que falla:

AtributoComprueba
requiredEl campo no está vacío (una casilla está marcada)
type="email", type="url"El valor parece una dirección de correo o una URL
minlength, maxlengthLa longitud del texto
min, max, stepEl rango de números y fechas
patternEl valor entero coincide con una expresión regular

:invalid y :valid dan estilo a los campos según su estado. :user-invalid suele ser mejor: solo se aplica después de que el lector haya cambiado el campo y pasado a otro, o haya intentado enviar, así que un formulario vacío no se abre lleno de rojo.

Hay tres cosas de pattern que confunden. Debe coincidir con el valor entero (no hacen falta ^ ni $). Solo se ejecuta cuando el campo no está vacío, así que combínalo con required. Y el mensaje de error del navegador es genérico, así que describe el formato con texto visible junto al campo. Chrome y Firefox añaden el texto de title a su mensaje, pero es fácil pasarlo por alto.

Para desactivar las comprobaciones, por ejemplo mientras pruebas la validación de tu servidor, añade novalidate al <form>. Un solo botón de envío puede saltárselas con formnovalidate.

La validación del navegador es una comodidad para el lector. Cualquiera puede editar la página o enviar una petición sin ella, así que el servidor debe volver a comprobar cada valor.

Mensajes personalizados con setCustomValidity

Cuando una regla no se puede escribir como atributo, como "las dos contraseñas deben coincidir", define el mensaje desde JavaScript. Un campo con un mensaje personalizado no vacío es no válido; una cadena vacía lo vuelve válido de nuevo:

El campo de repetición no tiene name, así que solo se envía una copia de la contraseña.

Gestionar el envío con JavaScript

Para enviar el formulario sin salir de la página, escucha submit, llama a preventDefault() y lee los campos con FormData. Escuchar submit en lugar del click de un botón captura todas las formas de enviar, incluido Enter, y solo se ejecuta después de que la validación integrada haya pasado:

Object.fromEntries(new FormData(form)) convierte los campos en un objeto simple. Para campos que pueden tener varios valores (casillas que comparten nombre, un select múltiple) usa formData.getAll('name'), porque el objeto solo conserva el último valor.

Errores comunes

  • Campos sin name. Se omiten sin avisar de los datos enviados.
  • Placeholders en lugar de etiquetas. La pista desaparece en cuanto el lector escribe. Usa un <label>.
  • Un <button> sin type usado para algo que no es enviar. Dentro de un formulario es un botón de envío.
  • Un formulario dentro de otro. Anidar formularios no es válido; el navegador ignora la etiqueta <form> interior.
  • Escuchar click en el botón de envío en lugar de submit en el formulario. Los envíos con la tecla Enter se pierden.
  • Confiar en la validación del navegador en el lado del servidor. Valida otra vez allí.
  • GET para contraseñas. Acaban en la URL, en el historial y en los registros del servidor.

Preguntas frecuentes

¿Cómo se crea un formulario en HTML?

Envuelve los campos en <form action="/signup" method="post">, dale a cada campo un name y un <label>, y termina con <button type="submit">. Al enviar el formulario, el navegador manda cada pareja name=value a la URL de action.

¿Qué diferencia hay entre GET y POST en un formulario?

method="get" (el valor por defecto) pone los campos en la URL, como en /search?q=shoes, lo que va bien para búsquedas y filtros que se puedan guardar en marcadores. method="post" los envía en el cuerpo de la petición, que es lo que quieres para inicios de sesión, registros y todo lo que modifica datos.

¿Por qué no se envía un campo de mi formulario?

No tiene atributo name, o está disabled. Solo se envían los campos con nombre y habilitados. Una casilla de verificación o un botón de opción sin marcar también se omite por completo.

¿Para qué sirven fieldset y legend?

<fieldset> agrupa campos relacionados y <legend> es el título del grupo. Los lectores de pantalla anuncian la leyenda cuando el foco entra en el grupo, que es lo que hace comprensible un grupo de botones de opción, y disabled en un fieldset deshabilita todos los campos que contiene.

¿Cómo valido un formulario en HTML sin JavaScript?

Usa atributos: required, type="email", minlength, maxlength, min, max y pattern. El navegador bloquea el envío y muestra un mensaje en el primer campo no válido. Valida siempre también en el servidor, porque estas comprobaciones se ejecutan en el navegador del lector y se pueden saltar.

¿Cómo evito que un formulario recargue la página?

Escucha el evento submit del formulario y llama a event.preventDefault(), luego envía tú los datos con fetch: form.addEventListener('submit', (e) => { e.preventDefault(); fetch(form.action, { method: 'POST', body: new FormData(form) }); }).

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR