acerca de HTML

Referencia de etiquetas

Etiqueta menu en HTML: listas de comandos y acciones

La etiqueta <menu> en HTML representa una lista de elementos que contienen comandos o acciones. Úsala para reunir los botones de una herramienta, como guardar y duplicar una nota o añadir y vaciar tareas. Describe el grupo de acciones; cada botón proporciona el control y la aplicación debe añadir la lógica de cada acción.

<menu>
  <li><button type="button">Guardar</button></li>
  <li><button type="button">Duplicar</button></li>
</menu>

Normalmente verás una lista con viñetas y dos botones. Puedes llegar a ellos con Tab y activarlos con Enter o Espacio, pero este fragmento todavía no guarda ni duplica nada: le faltan los handlers que ejecutan esas operaciones. type="button" pertenece al botón y evita que actúe como botón de envío si lo colocas en un formulario.

Sintaxis y contexto válido

Escribe <menu>…</menu> donde se permita contenido de flujo, por ejemplo dentro del cuerpo de la página o de una sección. No lo introduzcas dentro de un párrafo. Sus hijos directos pueden ser cero o más <li> y elementos de soporte de scripts, como <script> y <template>; los botones van dentro de los <li>.

Ambas etiquetas de <menu> se escriben explícitamente: ni la apertura ni el cierre se pueden omitir. El HTML Living Standard define este modelo de contenido. Un botón directamente bajo <menu> queda fuera de ese modelo, aunque el navegador lo muestre.

La elección depende de lo que reúnes:

  • <menu> expresa una lista de comandos, como «Añadir tarea» y «Vaciar lista».
  • <ul> expresa una lista general cuyo orden no determina su significado, como las tareas pendientes. También puede contener botones, pero no comunica específicamente la intención de agrupar comandos.
  • <nav> identifica una sección de navegación hacia otras páginas o partes de la página. Un menú principal con enlaces a «Inicio» y «Cursos» suele necesitar <nav> y puede organizar sus enlaces mediante <ul>.

La palabra «menú» en el diseño de una web no determina la etiqueta. Para enlaces de navegación, consulta la definición de <nav> en el estándar.

La semántica accesible implícita de <menu> es list, según ARIA en HTML. Los botones interiores conservan su comportamiento normal: Tab recorre los controles y Shift + Tab retrocede. La etiqueta no incorpora desplazamiento del foco con flechas, submenús ni un menú del sistema.

No añadas role="menu" solo por el nombre del elemento. Ese rol describe un widget compuesto con otra gestión del foco y del teclado. Implementarlo exige las relaciones, estados e interacciones del patrón de menú de WAI-ARIA, incluidas las flechas y el cierre cuando corresponda. Para una barra sencilla de botones, conserva la interacción nativa.

Ejemplo práctico: una barra de acciones para tareas

Guarda este documento como acciones.html en UTF-8 y ábrelo en el navegador. Incluye HTML, CSS y JavaScript; no necesita servidor, archivos adicionales ni servicios externos. Los cambios existen solo en la página abierta y desaparecen al recargar.

<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Acciones de la lista de tareas</title>
    <style>
      body {
        max-width: 42rem;
        margin-inline: auto;
        padding: 1rem;
        font-family: system-ui, sans-serif;
      }
      .menu-demo-acciones {
        display: flex;
        flex-wrap: wrap;
        gap: 0.75rem 2rem;
        padding-inline-start: 1.5rem;
      }
      .menu-demo-acciones button {
        font: inherit;
        padding: 0.45rem 0.75rem;
      }
      .menu-demo-acciones button:focus-visible {
        outline: 3px solid #164b92;
        outline-offset: 3px;
      }
    </style>
  </head>
  <body>
    <h1>Lista de tareas</h1>
    <p>Con JavaScript puedes añadir una tarea de ejemplo o vaciar
      la lista. Sin JavaScript puedes leerla; los botones quedan
      deshabilitados. Los cambios no se guardan.</p>

    <menu class="menu-demo-acciones">
      <li>
        <button id="menu-demo-anadir" type="button" disabled>
          Añadir tarea
        </button>
      </li>
      <li>
        <button id="menu-demo-vaciar" type="button" disabled>
          Vaciar lista
        </button>
      </li>
    </menu>

    <ul id="menu-demo-tareas">
      <li>Revisar el correo</li>
    </ul>
    <p id="menu-demo-estado" role="status">
      Las acciones requieren JavaScript; la lista se puede leer.
    </p>

    <script>
      const tareas = document.getElementById('menu-demo-tareas');
      const anadir = document.getElementById('menu-demo-anadir');
      const vaciar = document.getElementById('menu-demo-vaciar');
      const estado = document.getElementById('menu-demo-estado');
      let siguiente = 1;

      function actualizarEstado() {
        const total = tareas.children.length;
        estado.textContent = total === 1
          ? '1 tarea en la lista.'
          : `${total} tareas en la lista.`;
      }

      anadir.addEventListener('click', () => {
        const tarea = document.createElement('li');
        tarea.textContent = `Tarea nueva ${siguiente}`;
        siguiente += 1;
        tareas.append(tarea);
        actualizarEstado();
      });

      vaciar.addEventListener('click', () => {
        tareas.replaceChildren();
        actualizarEstado();
      });

      anadir.disabled = false;
      vaciar.disabled = false;
      actualizarEstado();
    </script>
  </body>
</html>
  1. Al abrirlo con JavaScript verás «Revisar el correo», dos botones habilitados y «1 tarea en la lista». El script está después del marcado que consulta.
  2. Pulsa Tab hasta «Añadir tarea» y Enter: aparecerá «Tarea nueva 1» y el contador indicará dos tareas. Espacio vuelve a activar el botón y añade «Tarea nueva 2».
  3. Pulsa Tab para llegar a «Vaciar lista» y actívalo: desaparecen todas las tareas y el mensaje pasa a «0 tareas en la lista». Puedes añadir otra después; el foco permanece en el botón utilizado.
  4. Deshabilita JavaScript y recarga. Permanecen la tarea inicial y la explicación, con los botones deshabilitados. Reduce el ancho de la ventana: flex-wrap permite que las acciones pasen a otra línea.

<menu> agrupa los comandos; <ul> contiene los datos que modifican. Si cambias <menu> por <ul> conservando la clase, los botones y los handlers, las acciones seguirán funcionando y la presentación será equivalente, pero perderás la distinción semántica de comandos. Si retiras solo las etiquetas del contenedor, dejarás sus <li> sueltos. Retirar el grupo completo elimina también sus controles: el script ya no puede consultar esos botones.

Atributos y accesibilidad

<menu> no tiene atributos específicos vigentes. Admite globales, como class para seleccionar el grupo desde CSS e id para identificarlo. En el ejemplo, type y disabled son atributos de <button>, no de <menu>. disabled es booleano: su presencia deshabilita; disabled="false" también lo mantiene deshabilitado. En JavaScript, la propiedad DOM .disabled = false sí habilita el botón.

display, gap y flex-wrap son propiedades CSS, y addEventListener() es un método de JavaScript: ninguno es un atributo de <menu>. La presentación horizontal la crea el CSS, no la etiqueta.

Los textos de los botones identifican sus acciones y el foco visible indica qué control vas a activar. role="status" en el párrafo permite exponer las actualizaciones del contador sin mover el foco. El anuncio concreto depende del navegador y del lector de pantalla. No añadas tabindex a cada <li> ni roles redundantes a los botones.

Errores frecuentes y preguntas

¿Menu crea un menú desplegable? No. La lista de acciones se presenta en el documento; mostrarla, ocultarla o implementar un desplegable requiere un diseño adicional.

¿Menu está obsoleta como menuitem? No. <menu> es vigente. <menuitem> pertenece a las funciones obsoletas del estándar. Los antiguos mecanismos de menús contextuales y atributos como type="context" no forman parte del uso actual. Tampoco uses el atributo histórico compact para modificar la apariencia: utiliza CSS.

¿Por qué los botones no hacen nada? Revisa si solo copiaste el fragmento mínimo, si JavaScript está habilitado, si los IDs coinciden y si el script se ejecuta después de crear los controles. Comprueba la consola para detectar errores; usar <menu> no conecta automáticamente las acciones.

Para profundizar, la guía de <li> explica cada entrada y la guía de <button> desarrolla los controles y sus tipos. Elige <ul> para listas generales y <nav> para secciones de navegación; la guía de <menuitem> sirve únicamente como referencia histórica.

Compatibilidad y fuentes

Consulta realizada el 5 de octubre de 2026: MDN clasifica <menu> como ampliamente disponible. Esto se refiere al elemento actual; no implica soporte de los antiguos menús contextuales. Su apariencia habitual se parece a la de <ul> y los estilos de la aplicación determinan cómo se distribuyen los controles.

Para significado, contenido permitido y atributos, usa la sección normativa de <menu>; para la semántica accesible, ARIA en HTML. La referencia de MDN complementa la explicación y la compatibilidad.