Etiqueta button en HTML: acciones y tipos de botón
La etiqueta <button> crea un botón cuya acción depende del tipo, del contexto y de los atributos o scripts asociados. Úsala para enviar un formulario, mostrar ayuda o ejecutar una acción sobre la página. Su texto indica qué ocurrirá al activarlo; escribir «Mostrar ayuda» no programa por sí solo esa función.
Un ejemplo mínimo de button
<button type="button">Mostrar ayuda</button>
Verás un control que puedes enfocar y activar. Todavía no aparecerá ayuda: no hay un comportamiento asociado. Si retiras las etiquetas y dejas únicamente el texto, tendrás texto corriente y perderás el control nativo.
Sintaxis y contenido permitido
Escribe apertura, contenido y cierre: <button type="button">Acción</button>. Puede aparecer donde se admite contenido de frase, por ejemplo dentro de un párrafo o un formulario. Puede contener texto, un <span> o una imagen, pero no otros controles interactivos, enlaces con href ni descendientes con tabindex.
Existe un contexto especial: como primer elemento hijo de un <select> personalizable puede contener también un <selectedcontent>. Ese botón es inerte y forma parte de la interfaz del selector; no es un botón de envío convencional. Son reglas propias del modelo de contenido de button.
Diferencias entre button, submit y reset
Valor de type | Comportamiento |
|---|---|
button | No envía ni restablece el formulario. Puedes asociarle JavaScript o un mecanismo declarativo admitido. |
submit | Inicia el envío del formulario asociado, con validación nativa cuando corresponda. |
reset | Restablece los controles del formulario a sus valores iniciales; no significa necesariamente dejarlos vacíos. |
En un formulario común, un botón sin type puede enviar accidentalmente los datos. El estándar actual llama Auto al estado de un valor ausente o inválido: se considera botón de envío cuando no tiene command ni commandfor y su padre no es <select>. Por eso conviene declarar siempre el tipo, sin generalizar el comportamiento a todos los contextos. Consulta la definición normativa de type.
Evita ofrecer reset junto a «Enviar» sin una necesidad clara: una pulsación equivocada puede hacer perder lo escrito.
Botón HTML frente a enlace
Usa <button> para acciones como revisar una solicitud o abrir ayuda. Para ir a otro documento, usa <a href="…">: el enlace permite copiar su destino o abrirlo en otra pestaña. Aplicar el mismo CSS a ambos no cambia su función.
Un botón deshabilitado tiene un estado nativo mediante disabled; <a> no admite ese atributo. No anides un enlace dentro del botón ni sustituyas el botón por un <div> pulsable: necesitarías reconstruir la semántica y la interacción de teclado.
<input type="submit" value="Enviar"> también envía un formulario. Elige <button> cuando quieras contenido dentro del control, por ejemplo texto acompañado de una imagen.
Ejemplo práctico: revisar una solicitud y mostrar ayuda
Guarda este documento como prueba-button.html y ábrelo en un navegador actual. No necesita archivos adicionales ni servidor. El envío se intercepta para registrar los datos y mostrar una vista previa: no se transmite ni se guarda la solicitud.
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Prueba de botones</title>
<style>
* { box-sizing: border-box; }
body { font-family: system-ui; max-width: 38rem; margin: auto; padding: 1rem; }
form { display: grid; gap: 0.75rem; max-width: 22rem; }
input, button { font: inherit; }
button { justify-self: start; }
</style>
</head>
<body>
<h1>Revisar una solicitud</h1>
<form id="demo-button-form">
<label for="demo-button-nombre">Nombre (obligatorio)</label>
<input id="demo-button-nombre" name="nombre" autocomplete="given-name" required>
<button type="submit" name="accion" value="revisar" disabled>
Revisar solicitud
</button>
<button id="demo-button-ayuda-control" type="button"
aria-controls="demo-button-ayuda" aria-expanded="false" hidden>
Mostrar ayuda
</button>
</form>
<p id="demo-button-ayuda">Escribe el nombre que quieres usar en la solicitud.</p>
<p id="demo-button-resultado" role="status"></p>
<noscript>
<p>La ayuda permanece visible. Activa JavaScript para probar la revisión local;
el envío está deshabilitado porque esta demostración no tiene servidor.</p>
</noscript>
<p><a href="https://html.spec.whatwg.org/multipage/">Consultar el estándar de HTML</a></p>
<script>
const formulario = document.getElementById("demo-button-form");
const enviar = formulario.querySelector('button[type="submit"]');
const control = document.getElementById("demo-button-ayuda-control");
const ayuda = document.getElementById("demo-button-ayuda");
const resultado = document.getElementById("demo-button-resultado");
control.addEventListener("click", () => {
ayuda.hidden = !ayuda.hidden;
control.setAttribute("aria-expanded", String(!ayuda.hidden));
control.textContent = ayuda.hidden ? "Mostrar ayuda" : "Ocultar ayuda";
});
formulario.addEventListener("submit", (evento) => {
evento.preventDefault();
const datos = new FormData(formulario, evento.submitter);
console.log("Revisión local:", Object.fromEntries(datos));
resultado.textContent = `Vista previa para ${datos.get("nombre")}. No se ha enviado nada.`;
});
ayuda.hidden = true;
control.hidden = false;
enviar.disabled = false;
</script>
</body>
</html>
Prueba estas acciones:
- Pulsa Tab hasta «Mostrar ayuda» y actívalo con Espacio o Enter. La ayuda aparece, cambia el texto del botón y
aria-expandedpasa atrue; el foco permanece en el control. - Intenta revisar sin nombre: la validación impide el envío. Escribe «Ana» y activa «Revisar solicitud»: verás «Vista previa para Ana. No se ha enviado nada.». La consola registra
nombre: "Ana"yaccion: "revisar". - Abre el enlace: navega a otro documento, sin revisar el formulario.
- Deshabilita JavaScript y recarga. La ayuda está visible, su botón se oculta y «Revisar solicitud» queda deshabilitado, con una explicación.
Si quitas type="button" al botón de ayuda, en este formulario también puede iniciar la revisión. Si quitas el script, no habrá revisión local: se conserva la alternativa del paso 4. El segundo argumento de FormData incluye los datos del botón que inició el envío.
Atributos del botón y del envío
| Atributo | Uso |
|---|---|
disabled | Booleano: impide activar y enfocar el botón. disabled="false" también lo deshabilita; para habilitarlo, retira el atributo. |
name y value | Identifican un dato de envío. El botón aporta ese par si fue el que inició el envío; value no reemplaza su texto visible. |
form | ID del formulario asociado en el mismo documento. Permite situar el botón fuera de él. Sin este atributo, normalmente se asocia al formulario antecesor. |
formaction | Sustituye la URL de action para ese envío. |
formenctype | Sustituye la codificación, por ejemplo multipart/form-data para archivos. |
formmethod | Sustituye el método, como get o post; dialog tiene un uso especial para cerrar un diálogo sin transmitir datos. |
formnovalidate | Booleano: omite la validación nativa en ese envío. |
formtarget | Sustituye el destino de presentación, como _self o _blank. |
Los cinco atributos de envío form* se usan en botones de envío; si se omiten, se aplican los ajustes del formulario. Consulta los atributos de envío del estándar y la referencia de button en MDN.
id, class y lang son atributos globales. font pertenece a CSS; enviar.disabled = false modifica una propiedad DOM desde JavaScript. No son tipos adicionales de botón.
Nombre accesible y foco
Prefiere textos visibles que nombren la acción, como «Revisar solicitud». Un icono solo necesita un nombre accesible, por ejemplo aria-label="Cerrar ayuda"; title no debe ser su única explicación. Conserva el indicador de foco y no añadas role="button" a un botón nativo. Los estados deben comunicarse también con texto o atributos apropiados, no únicamente con color. Las teclas y el foco del ejemplo siguen el patrón de botón de WAI.
Preguntas frecuentes
¿Por qué mi botón envía el formulario? Comprueba type, el formulario asociado —incluido form— y cualquier manejador de eventos. Declara type="button" para una acción secundaria. Revisa también si tu script llama a requestSubmit().
¿Button necesita JavaScript? Un submit puede usar el envío nativo hacia un destino real. Mostrar ayuda como en esta demo requiere el script, aunque algunas acciones tienen mecanismos declarativos. Si un type="button" no hace nada, comprueba que exista ese comportamiento y que el script haya cargado.
Comandos declarativos y compatibilidad
popovertarget identifica un elemento con popover; popovertargetaction permite toggle —predeterminado—, show o hide. commandfor señala el elemento controlado y command elige una acción admitida, como show-modal para <dialog>. Estos mecanismos pueden evitar scripts para acciones concretas; no convierten cualquier texto de acción en una función.
Compatibilidad consultada el 3 de octubre de 2026: <button> tiene soporte amplio, pero las funciones adicionales tienen sus propios requisitos:
| Función | Primeras versiones registradas |
|---|---|
popovertarget | Chrome 114, Firefox 125, Safari 17. |
command y commandfor | Chrome 135, Firefox 144, Safari 26.2. |
Estos datos proceden del catálogo de compatibilidad de MDN para button. En versiones anteriores, conserva una alternativa visible o una implementación con scripts comprobada. El soporte de un <select> personalizable se evalúa por separado; no se deduce del soporte general del botón.