elemento HTML vigente

<form>

Formularios

Contenedor que agrupa los controles de un formulario y define cómo se envían los datos al servidor: qué URL recibe los datos (action), con qué método HTTP viajan (method) y si el navegador puede omitir la validación nativa (novalidate).

<form> es el contenedor que convierte un conjunto de controles HTML en un formulario funcional. Sin él, los <input>, <textarea>, <select> y <button> de una página son elementos independientes sin coordinación: existen visualmente, pero no comparten ni envían datos como una unidad. <form> les da un contexto común: define adónde van los datos, cómo viajan, y cuál es el botón que dispara el envío.

El mecanismo central de <form> es el envío: cuando el usuario activa un control type="submit" (un botón o un input de tipo submit), el navegador recoge todos los controles del formulario que tienen un atributo name, construye un conjunto de pares nombre=valor y los envía al servidor según lo que digan action y method. Este proceso ocurre sin JavaScript: es el comportamiento nativo del navegador, anterior a cualquier framework.

Cada control dentro del formulario necesita el atributo name para participar en el envío. El name es literalmente la clave del par clave-valor en la petición HTTP. Un <input type="email" id="correo"> sin name renderiza perfectamente, el usuario puede tipear en él, pero su valor no se incluye en los datos enviados. El id identifica el elemento en el DOM (lo usan el CSS, el JS y el <label for>); el name es la clave de envío al servidor — son dos atributos distintos con propósitos distintos.

<form action="/registro" method="post"> <label> + <input name="nombre"> <label> + <input name="correo"> Enviar servidor nombre=Ana correo=ana@x.com </form>

Cómo funciona

Cuando el usuario hace clic en un botón type="submit" (o presiona Enter en un campo de texto), el navegador recorre el <form> buscando todos los controles habilitados que tengan name. Por cada uno construye un par nombre=valor usando el name como clave y el valor actual del control como valor. Luego envía esa colección al servidor según action y method.

Si method="get", los pares se serializan como query string y se adjuntan a la URL (/buscar?q=html&lang=es). Si method="post", viajan en el cuerpo de la petición HTTP, invisible en la barra de direcciones. La respuesta del servidor puede ser una nueva página, una redirección, o —en aplicaciones modernas— JSON que JavaScript procesa sin recargar.

Modelo de contenido

<form> es un elemento de bloque que puede contener cualquier contenido de flujo, excepto otro <form> anidado (está prohibido por spec). En la práctica contiene <fieldset>, <div>, <p>, <label>, <input>, <textarea>, <select>, <button>, y cualquier otro elemento de estructuración. El <form> no renderiza ningún elemento visual propio; su efecto es puramente funcional.

Display por defecto: block.

Sintaxis

<!-- Formulario básico: envía datos al servidor como POST -->
<form action="/registro" method="post">
  <label for="nombre">Nombre</label>
  <input type="text" id="nombre" name="nombre">

  <label for="correo">Correo electrónico</label>
  <input type="email" id="correo" name="correo">

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


Atributos

action — URL de destino

Define la URL que recibirá los datos del formulario. Si se omite, los datos se envían a la URL de la página actual.

<form action="/api/registro" method="post">…</form>

Default: URL de la página actual.

Gotcha: en aplicaciones de una sola página (SPA) con JavaScript, frecuentemente se omite action y se intercepta el envío con event.preventDefault() para manejar los datos con fetch/XHR. El atributo sigue siendo útil como fallback cuando JS falla.

method — método HTTP de envío

Determina cómo viajan los datos. Acepta dos valores relevantes para formularios HTML:

get — los datos van en la URL como query string (/buscar?q=html). La petición es visible, guardable como bookmark, compartible por URL. Usalo para búsquedas y filtros: datos no sensibles donde la URL resultante tiene significado y puede marcarse como favorito.

post — los datos van en el cuerpo de la petición HTTP, fuera de la URL. La petición no es visible en la barra de direcciones. Usalo para acciones que modifican datos: crear cuenta, enviar mensaje, procesar pago. También es obligatorio cuando el formulario incluye archivos (<input type="file">).

<!-- GET: para búsquedas — la URL resultante es /buscar?q=html -->
<form action="/buscar" method="get">
  <input type="search" name="q">
  <button type="submit">Buscar</button>
</form>

<!-- POST: para envío de datos sensibles o destructivos -->
<form action="/registro" method="post">
  <input type="password" name="clave">
  <button type="submit">Registrarse</button>
</form>

Default: get.

Gotcha: olvidar cambiar a post en formularios con contraseñas hace que la contraseña aparezca en la URL, en los logs del servidor, y en el historial del navegador.

novalidate — deshabilitar validación nativa

Atributo booleano. Cuando está presente, el navegador envía el formulario sin ejecutar la validación HTML nativa (los atributos required, pattern, min, max). Útil cuando se implementa validación personalizada con JavaScript y no se quiere que la del navegador interfiera.

<form action="/registro" method="post" novalidate>…</form>

Default: no presente (la validación nativa está activa).

enctype — codificación del cuerpo

Solo aplica cuando method="post". Define cómo se codifican los datos en el cuerpo de la petición.

ValorCuándo usarlo
application/x-www-form-urlencoded (default)Todos los formularios sin archivos
multipart/form-dataObligatorio cuando el form incluye <input type="file">
text/plainRaro; solo para pruebas simples
<!-- Si el formulario sube archivos, enctype es obligatorio -->
<form action="/subir" method="post" enctype="multipart/form-data">
  <input type="file" name="foto">
  <button type="submit">Subir</button>
</form>

Gotcha frecuente: olvidar enctype="multipart/form-data" al subir archivos hace que el servidor no reciba el archivo, solo el nombre. La causa es difícil de diagnosticar si no se sabe el mecanismo.

autocomplete — sugerencias del navegador

Controla si el navegador puede autocompletar los campos del formulario con datos guardados (nombre, dirección, correo, contraseña).

<!-- Deshabilitar autocomplete en todo el formulario -->
<form action="/perfil" method="post" autocomplete="off">…</form>

Default: on. Se puede sobrescribir a nivel de cada <input> individual.

target — dónde mostrar la respuesta

Define en qué contexto de navegación se abre la respuesta del servidor. Funciona igual que en <a>: _self (default, misma pestaña), _blank (nueva pestaña), o el nombre de un <iframe>. Raro en uso moderno.

Estados e interacción

<form> no tiene pseudoclases propias, pero dispara el evento submit al enviarse. En JavaScript: form.addEventListener('submit', fn). El evento llega antes del envío real; event.preventDefault() lo cancela y permite procesamiento personalizado.

Los controles dentro del form tienen su propio estado (:focus, :disabled, :valid, :invalid) — ver la entrada de <input>.

Accesibilidad

<form> tiene rol implícito form en el árbol de accesibilidad, pero solo cuando tiene un nombre accesible (atributo aria-label o aria-labelledby). Sin nombre, algunos lectores de pantalla no lo anuncian como región de formulario. Para formularios con significado propio (un formulario de búsqueda separado del contenido principal), agregá aria-label:

<form action="/buscar" method="get" aria-label="Buscador del sitio">
  <input type="search" name="q">
  <button type="submit">Buscar</button>
</form>

El agrupador de controles relacionados dentro del form es <fieldset> con <legend> — ver esa entrada para el patrón de accesibilidad.

Cuándo usar get vs post

SituaciónMétodo
Búsqueda, filtros, paginaciónget (la URL es compartible)
Login, registro, contraseñaspost (datos sensibles)
Crear / modificar / eliminar datospost (acción con efecto en el servidor)
Subir archivospost + enctype="multipart/form-data"

Notas, gotchas e interacción

  • Sin name no hay datos. Un control sin atributo name no se incluye en el envío, aunque tenga id y el usuario haya tipeado algo. Es el error más frecuente en formularios que “no envían”.
  • method="get" y datos sensibles. Las contraseñas y tokens enviados por GET quedan en la URL, en el historial del navegador, en los logs del servidor y en los headers Referer. Nunca GET para datos sensibles.
  • Botón de submit fuera del form. Un <button> puede estar fuera del <form> y aun así enviarlo si tiene el atributo form apuntando al id del form: <button type="submit" form="mi-form">. Útil para formularios donde el botón debe ir en otro lugar del layout.
  • Doble submit. Si el servidor tarda, el usuario puede hacer clic dos veces. Prevención: deshabilitar el botón en el evento submit con JS.

Vigente / legacy

<form> está completamente vigente. Los atributos accept-charset (para especificar la codificación de caracteres aceptada) y el uso de frames como target son legacy y raramente necesarios hoy. El atributo accept en el propio <form> (para tipos MIME) fue removido del spec; el filtro de tipo de archivo se hace en <input type="file" accept="...">.