Cómo crear menús accesibles con Bootstrap o Tailwind

Cómo crear menús accesibles con Bootstrap y Tailwind
Solucionex
24
Sep 25

Los menús de navegación son uno de los componentes más importantes de cualquier sitio web. Si no están bien implementados, pueden ser una barrera enorme para usuarios de lectores de pantalla o personas que navegan solo con teclado.

En este post vamos a ver cómo hacerlos totalmente accesibles, primero con Bootstrap (que ya nos ayuda bastante) y luego con Tailwind (donde tendremos que armar la lógica).

Principios de accesibilidad web en un menú

  1. Estructura semántica correcta

    • Usar <nav> para envolver la navegación principal.

    • Usar listas <ul> y <li> para los enlaces.

  2. Soporte de teclado

    • Tab → moverse entre enlaces.

    • Enter o Space → abrir/cerrar submenús.

    • ↑ ↓ ← → → moverse entre elementos del submenú.

    • Esc → cerrar un submenú abierto.

  3. Roles y atributos ARIA

    • aria-haspopup="true" y aria-expanded en botones que despliegan submenús.

    • Submenús con role="menu" y role="menuitem".

    • Relación con aria-controls y aria-labelledby.

Menú accesible con Bootstrap 5

Bootstrap ya resuelve buena parte, pero debemos respetar la semántica:

<nav class="navbar navbar-expand-lg navbar-light bg-light" aria-label="Menú principal">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Marca</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" 
            data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
            aria-expanded="false" aria-label="Abrir menú">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" href="#" aria-current="page">Inicio</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
             data-bs-toggle="dropdown" aria-expanded="false" aria-haspopup="true">
            Servicios
          </a>
          <ul class="dropdown-menu" aria-labelledby="navbarDropdown" role="menu">
            <li><a class="dropdown-item" href="#" role="menuitem">Servicio 1</a></li>
            <li><a class="dropdown-item" href="#" role="menuitem">Servicio 2</a></li>
          </ul>
        </li>
      </ul>
    </div>
  </div>
</nav>

👉 Bootstrap gestiona aria-expanded, roles y soporte de teclado de forma automática.

Menú accesible con Tailwind

Con Tailwind hay que programar la lógica de despliegue de submenús:

<nav class="bg-gray-100 p-4" aria-label="Menú principal">
  <ul class="flex space-x-4">
    <li><a href="#" class="hover:underline">Inicio</a></li>
    
    <li class="relative">
      <button id="menu-button" aria-haspopup="true" aria-expanded="false"
              aria-controls="submenu"
              class="hover:underline focus:outline-none focus:ring">
        Servicios
      </button>
      <ul id="submenu" class="hidden absolute left-0 mt-2 bg-white border shadow rounded"
          role="menu" aria-labelledby="menu-button">
        <li><a href="#" class="block px-4 py-2 hover:bg-gray-200" role="menuitem">Servicio 1</a></li>
        <li><a href="#" class="block px-4 py-2 hover:bg-gray-200" role="menuitem">Servicio 2</a></li>
      </ul>
    </li>
  </ul>
</nav>

<script>
  const button = document.getElementById("menu-button");
  const submenu = document.getElementById("submenu");

  button.addEventListener("click", () => {
    const expanded = button.getAttribute("aria-expanded") === "true";
    button.setAttribute("aria-expanded", !expanded);
    submenu.classList.toggle("hidden", expanded);
  });

  // Cerrar con Esc
  button.addEventListener("keydown", (e) => {
    if (e.key === "Escape") {
      button.setAttribute("aria-expanded", "false");
      submenu.classList.add("hidden");
      button.focus();
    }
  });
</script>

👉 Aquí:

  • aria-haspopup y aria-expanded indican el estado del submenú.

  • El submenú se cierra al pulsar Esc.

  • Puedes mejorar añadiendo navegación con flechas para mover entre elementos.

Conclusión

  • Los menús son el componente más crítico en términos de accesibilidad web.

  • Con Bootstrap gran parte del trabajo está hecho, solo debes mantener una estructura correcta.

  • Con Tailwind hay que programar la lógica, pero con ARIA y un poco de JS se consigue un menú totalmente inclusivo.

Accesibilidad Web
Bootstrap
tailwindcss
Maquetación
Frontend