Cómo crear la navegación principal para un sitio web

En este instructivo, se describe cómo crear una navegación principal accesible para un sitio web. Aprendiste sobre el HTML semántico, la accesibilidad y cómo el uso de atributos ARIA a veces puede hacer más daño que bien.

Manuel Matuzović
Manuel Matuzović

Existen muchas formas diferentes de compilar la navegación principal de un sitio web, en términos de diseño, funcionalidad y el lenguaje de marcado y la información semántica subyacentes. Si la implementación es demasiado minimalista, funciona para la mayoría de las personas, pero es posible que la experiencia del usuario (UX) no sea excelente. Si se diseña de forma excesiva, puede confundir a los usuarios o incluso impedir que accedan a ella.

En la mayoría de los sitios web, se busca crear algo que no sea demasiado simple ni demasiado complicado.

Compilación capa por capa

En este instructivo, comenzarás con una configuración básica y agregarás funciones capa por capa hasta un punto en el que proporciones la información, el estilo y la funcionalidad suficientes para complacer a la mayoría de los usuarios. Para lograrlo, utiliza el principio de mejora progresiva, que establece que se debe comenzar con la solución más fundamental y sólida, y agregar capas de funcionalidad de forma progresiva. Si una capa no funciona por algún motivo, la navegación seguirá funcionando porque recurre de forma correcta a la capa subyacente.

Estructura básica

Para una navegación básica, necesitas dos cosas: elementos <a> y algunas líneas de CSS para mejorar el diseño y el estilo predeterminados de tus vínculos.

  • HTML

    <a href="/home">Home</a>
    <a href="/about-us">About us</a>
    <a href="/pricing">Pricing</a>
    <a href="/contact">Contact</a>
    
  • CSS

    /* Define variables for your colors */
    :root {
      --color-shades-dark: rgb(25, 25, 25);
    }
    
    /* Use the alternative box model
    Details: <https://web.dev/learn/css/box-model/> */
    *{
      box-sizing: border-box;
    }
    
    /* Basic font styling */
    body {
      font-family: Segoe UI, system-ui, -apple-system, sans-serif;
      font-size: 1.6rem;
    }
    
    /* Link styling */
    a {
      --text-color: var(--color-shades-dark);
      border-block-end: 3px solid var(--border-color, transparent);
      color: var(--text-color);
      display: inline-block;
      margin-block-end: 0.5rem; /* See note at the bottom of this chapter */
      margin-inline-end: 0.5rem;
      padding: 0.1rem;
      text-decoration: none;
    }
    
    /* Change the border-color on :hover and :focus */
    a:where(:hover, :focus) {
      --border-color: var(--text-color);
    }
    
Consulta el paso 1: HTML básico y CSS" en CodePen.

Esto funciona bien para la mayoría de los usuarios, sin importar cómo accedan al sitio. Se puede acceder a la navegación con un mouse, un teclado, un dispositivo táctil o un lector de pantalla, pero hay margen de mejora. Puedes mejorar la experiencia extendiendo este patrón básico con funciones e información adicionales.

Puedes hacer lo siguiente:

  • Destaca la página activa.
  • Anuncia la cantidad de elementos a los usuarios de lectores de pantalla.
  • Agrega un punto de referencia y permite que los usuarios de lectores de pantalla accedan a la navegación directamente con una combinación de teclas.
  • Ocultar la navegación en viewports estrechos
  • Mejorar el diseño del foco

Destaca la página activa

Para destacar la página activa, puedes agregar una clase al vínculo correspondiente.

<a href="/about-us" class="active-page">About us</a>

El problema con este enfoque es que transmite la información de qué vínculo está activo de forma puramente visual. Un usuario ciego que use un lector de pantalla no podría distinguir entre la página activa y las demás. Afortunadamente, el estándar de Aplicaciones de Internet enriquecidas y accesibles (ARIA) también ofrece una forma de comunicar esta información de manera semántica. Usa el atributo y el valor aria-current="page" en lugar de una clase.

aria-current (estado) indica el elemento que representa el elemento actual dentro de un contenedor o conjunto de elementos relacionados. Es un token de página que se usa para indicar un vínculo dentro de un conjunto de vínculos de paginación, en el que el vínculo tiene un estilo visual que representa la página que se muestra actualmente. [Aplicaciones de Internet enriquecidas accesibles (WAI-ARIA) 1.1](https://www.w3.org/TR/wai-aria/#aria-current)

Con el atributo adicional, un lector de pantalla ahora anuncia algo como "página actual, vínculo, Acerca de nosotros" en lugar de solo "vínculo, Acerca de nosotros".

<a href="/about-us" aria-current="page" class="active-page">About us</a>

Un efecto secundario conveniente es que puedes usar el atributo para seleccionar el vínculo activo en CSS, lo que hace que la clase active-page quede obsoleta.

<a href="/home">Home</a>
<a href="/about-us" aria-current="page">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Change border-color and color for the active page */
[aria-current="page"] {
  --border-color: var(--color-highlight);
  --text-color: var(--color-highlight);
}
Consulta el Paso 2: Destaca la página activa en CodePen.

Anunciar la cantidad de elementos

Al mirar la navegación, los usuarios videntes pueden notar que solo contiene cuatro vínculos. Un usuario ciego que usa un lector de pantalla no puede obtener esta información con la misma rapidez. Es posible que deban revisar toda la lista de vínculos. Esto podría no ser un problema si la lista es corta, como en este ejemplo, pero si contiene 40 vínculos, esta tarea puede ser engorrosa. Si un usuario de lector de pantalla sabe de antemano que la navegación contiene muchos vínculos, podría decidir usar una forma de navegación diferente y más eficiente, como la búsqueda en el sitio.
Una buena forma de comunicar la cantidad de elementos por adelantado es unir cada vínculo en un elemento de lista (<li>), anidado en una lista sin ordenar (<ul>).

<ul>
  <li>
     <a href="/home">Home</a>
  </li>
  <li>
    <a href="/about-us" aria-current="page">About us</a>
  </li>
  <li>
    <a href="/pricing">Pricing</a>
  </li>
  <li>
    <a href="/contact">Contact</a>
  </li>
</ul>

Cuando un usuario de lector de pantalla encuentre la lista, su software anunciará algo como "lista, 4 elementos".

Aquí tienes una demostración de la navegación que se usa con el lector de pantalla NVDA en Windows.

Ahora debes adaptar el diseño para que se vea como antes.

/* Remove the default list styling and create a flexible layout for the list */
ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Basic link styling */
a {
  --text-color: var(--color-shades-dark);

  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  padding: 0.1rem;
  text-decoration: none;
}

Usar listas puede tener muchas ventajas para los usuarios de lectores de pantalla:

  • Pueden obtener la cantidad total de elementos antes de interactuar con ellos.
  • Es posible que usen combinaciones de teclas para saltar de un elemento de la lista a otro.
  • Es posible que usen combinaciones de teclas para saltar de una lista a otra.
  • Es posible que el lector de pantalla anuncie el índice del elemento actual (por ejemplo, "elemento de lista, dos de cuatro").

Además, si la página se presenta sin CSS, la lista muestra los vínculos como un grupo coherente de elementos en lugar de solo un montón de vínculos.

Un detalle notable sobre VoiceOver en Safari es que pierdes todas estas ventajas cuando configuras list-style: none. Se diseñó de este modo. El equipo de WebKit decidió quitar la semántica de lista cuando una lista no parece una lista. Según la complejidad de tu navegación, esto puede ser un problema o no. Por un lado, la navegación sigue siendo utilizable y solo afecta a VoiceOver en Safari. VoiceOver con Chrome o Firefox sigue anunciando la cantidad de elementos, al igual que otros lectores de pantalla, como NVDA. Por otro lado, la información semántica podría ser muy útil en algunas situaciones. Para tomar esa decisión, debes probar la navegación con usuarios reales de lectores de pantalla y obtener sus comentarios. Si decides que necesitas que VoiceOver en Safari se comporte como todos los demás lectores de pantalla, puedes solucionar el problema configurando el rol de lista de ARIA de forma explícita en el <ul>. Esto revierte el comportamiento al estado anterior a que quitaras el diseño de la lista. Visualmente, la lista sigue siendo la misma.

<ul role="list">
  <li>
     <a href="/home">Home</a>
  </li>
  ...
</ul>
Consulta el Paso 3: Anuncia la cantidad de elementos en CodePen.

Cómo agregar un punto de referencia

Con poco esfuerzo, realizaste grandes mejoras para los usuarios de lectores de pantalla, pero hay algo más que puedes hacer. La navegación sigue siendo semánticamente solo una lista de vínculos y es difícil saber que esta lista específica es la navegación principal de tu sitio web. Puedes convertir esta lista común en una lista de navegación uniendo el elemento <ul> en un elemento <nav>.

Usar el elemento <nav> tiene varias ventajas. En particular, un lector de pantalla anuncia algo como "navegación" cuando el usuario interactúa con él y agrega un punto de referencia a la página. Los puntos de referencia son regiones especiales de la página, como <header>, <footer> o <main>, a las que puede saltar un lector de pantalla. Tener puntos de referencia en una página puede ser útil, ya que permite que los usuarios de lectores de pantalla accedan directamente a regiones importantes de la página sin tener que interactuar con el resto de ella. Por ejemplo, puedes saltar de un punto de referencia a otro presionando la tecla D en NVDA. En VoiceOver, puedes usar el rotor para enumerar todos los puntos de referencia de la página presionando VO + U.

Una lista de cuatro puntos de referencia: banner, navegación, principal, información de contenido.
Rotor en VoiceOver que enumera todos los puntos de referencia de una página.

En esta lista, verás 4 puntos de referencia: banner, que es el elemento <header>; navigation, que es el elemento <nav>; main, que es el elemento <main>; y content information, que es el elemento <footer>. Esta lista no debe ser demasiado larga, ya que solo debes marcar las partes fundamentales de tu IU como puntos de referencia, como la búsqueda en el sitio, la navegación local o la paginación.

Si tienes una navegación para sitio completo, una navegación local para la página y una paginación en una sola página, es posible que también tengas 3 elementos <nav>. Eso está bien, pero ahora hay tres puntos de referencia de navegación y, semánticamente, todos se ven iguales. Es difícil distinguirlos, a menos que conozcas muy bien la estructura de la página.

Imagen que muestra tres puntos de referencia que dicen &quot;navigation&quot;.
El rotor de VoiceOver muestra tres puntos de referencia de navegación sin etiquetar.

Para que se puedan distinguir, debes etiquetarlos con aria-labelledby o aria-label.

<nav aria-label="Main">
    <ul>
      <li>
         <a href="/home">Home</a>
      </li>
      ...
  </ul>
</nav>
...
<nav aria-label="Select page">
    <ul>
      <li>
         <a href="/page-1">1</a>
      </li>
      ...
    </ul>
</nav>

Si la etiqueta que elegiste ya existe en algún lugar de la página, puedes usar aria-labelledby en su lugar y hacer referencia a la etiqueta existente con el atributo id.

<nav aria-labelledby="pagination_heading">
  <h2 id="pagination_heading">Select a page</h2>
  <ul>
    <li>
       <a href="/page-1">1</a>
    </li>
    ...
  </ul>
</nav>

Una etiqueta concisa es suficiente, no uses demasiadas palabras. Omite expresiones como "navegación" o "menú", ya que el lector de pantalla ya proporciona esta información a los usuarios.

Puntos de referencia
VoiceOver muestra los puntos de referencia "banner", "main navigation", "main", "Navegación de páginas", "select page navigation" y "content info".
Consulta el Paso 4: Agrega un punto de referencia en CodePen.

Ocultar la navegación en viewports estrechos

Personalmente, no me gusta ocultar la navegación principal en viewports estrechos, pero si la lista de vínculos es demasiado larga, no hay otra opción. Si ese es el caso, en lugar de la lista, los usuarios ven un botón con la etiqueta "Menú", un ícono de hamburguesa o una combinación de ambos. Si haces clic en el botón, se mostrará y ocultará la lista. Si conoces los conceptos básicos de JavaScript y CSS, es una tarea factible, pero hay varios aspectos relacionados con la UX y la accesibilidad que debes tener en cuenta.

  • Debes ocultar la lista de forma accesible.
  • La navegación debe ser accesible con el teclado.
  • La navegación debe comunicar si es visible o no.

Cómo agregar un botón de menú de hamburguesa

Como estás siguiendo el principio de mejora progresiva, debes asegurarte de que la navegación siga funcionando y tenga sentido incluso con JavaScript desactivado.
Lo primero que necesita la navegación es un botón de menú de opciones. Lo creas en HTML en un elemento de plantilla, lo clonas en JavaScript y lo agregas a la navegación.

Una página que muestra un botón de menú de opciones.
Resultado: En lugar de vínculos, la navegación muestra un botón de menú de opciones en viewports estrechos.
<nav id="mainnav">
  ...
</nav>

<template id="burger-template">
  <button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
    <svg width="24" height="24" aria-hidden="true">
      <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z">
    </svg>
  </button>
</template>
  1. El atributo aria-expanded le indica al software de lector de pantalla si el elemento que controla el botón está expandido o no.
  2. aria-label le da al botón un nombre de accesibilidad, un texto alternativo para el ícono de hamburguesa.
  3. Ocultas el <svg> de la tecnología de accesibilidad con aria-hidden porque ya tiene una etiqueta de texto proporcionada por aria-label.
  4. aria-controls le indica a la tecnología de accesibilidad que admite el atributo (por ejemplo, JAWS) qué elemento controla el botón.
const nav = document.querySelector('#mainnav')
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const button = burgerClone.querySelector('button');

// Toggle aria-expanded attribute
button.addEventListener('click', e => {
  // aria-expanded="true" signals that the menu is currently open
  const isOpen = button.getAttribute('aria-expanded') === "true"
  button.setAttribute('aria-expanded', !isOpen);
});

// Hide list on keydown Escape
nav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    button.setAttribute('aria-expanded', false);
  }
});

// Add the button to the page
nav.insertBefore(burgerClone, list);
  1. Es conveniente que los usuarios puedan cerrar la navegación cuando quieran, por ejemplo, presionando la tecla Escape.
  2. Es importante usar insertBefore en lugar de appendChild porque el botón debe ser el primer elemento de la navegación. Si un usuario de teclado o lector de pantalla presiona Tab después de hacer clic en el botón, espera enfocar el primer elemento de la lista. Si el botón aparece después de la lista, no sería así.

A continuación, restablece el diseño predeterminado del botón y asegúrate de que solo sea visible en viewports estrechos.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
  }
}

/* Reset button styling */
button {
  all: unset;
  display: var(--nav-button-display, flex);
}
Consulta el Paso 5: Agrega un botón de menú de opciones en CodePen.

Ocultar la lista

Antes de ocultar la lista, posiciona y aplica diseño a la navegación y a la lista para que el diseño esté optimizado para viewports estrechos, pero que se vea bien en pantallas más grandes.
Primero, quita el <nav> del flujo natural de la página y colócalo en la esquina superior del viewport.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
}

nav {
  position: var(--nav-position, fixed);
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
}

A continuación, cambia el diseño en los viewports estrechos agregando una nueva propiedad personalizada (—-nav-list-layout). El diseño es de columna de forma predeterminada y cambia a fila en pantallas más grandes.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }

  ul {
    --nav-list-layout: row;
  }
}

ul {
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

La navegación debería verse de la siguiente manera en viewports estrechos.

La página muestra la lista de navegación y el botón de menú de opciones.
Tanto el botón de menú de tres líneas como la lista se colocan en la esquina superior derecha del viewport.

La lista obviamente necesita algo de CSS. La moveremos a la esquina superior, haremos que ocupe toda la pantalla verticalmente, aplicaremos un background-color y un box-shadow.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
  
  ul {
    --nav-list-layout: row;
    --nav-list-position: static;
    --nav-list-padding: 0;
    --nav-list-height: auto;
    --nav-list-width: 100%;
    --nav-list-shadow: none;
  }
}

ul {
  background: rgb(255, 255, 255);
  box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  height: var(--nav-list-height, 100vh);
  list-style: none;
  margin: 0;
  padding: var(--nav-list-padding, 2rem);
  position: var(--nav-list-position, fixed);
  inset-block-start: 0; /* Logical property. Equivalent to top: 0; */
  inset-inline-end: 0; /* Logical property. Equivalent to right: 0; */
  width: var(--nav-list-width, min(22rem, 100vw));
}

button {
  all: unset;
  display: var(--nav-button-display, flex);
  position: relative;
  z-index: 1;
}

La lista debería verse de la siguiente manera en viewports estrechos, más como una barra lateral que como una lista simple.

Se abrirá la lista de navegación.

Por último, oculta la lista, muéstrala solo cuando el usuario haga clic en el botón una vez y ocúltala cuando vuelva a hacer clic. Es importante ocultar solo la lista y no toda la navegación, ya que ocultar la navegación también significaría ocultar un punto de referencia importante.

Anteriormente, agregaste un evento de clic al botón para activar o desactivar el valor del atributo aria-expanded. Puedes usar esa información como condición para mostrar y ocultar la lista en CSS.

@media (min-width: 48em) {
  ul {
    --nav-list-visibility: visible;
  }
}

ul {
  visibility: var(--nav-list-visibility, visible);
}

/* Hide the list on narrow viewports, if it comes after an element with
   aria-expanded set to "false". */
[aria-expanded="false"] + ul {
  visibility: var(--nav-list-visibility, hidden);
}

Es importante usar una declaración de propiedad como visibility: hidden o display: none en lugar de opacity: 0 o translateX(100%) para ocultar la lista. Estas propiedades garantizan que no se pueda enfocar en los vínculos cuando la navegación está oculta. Si usas opacity o translate, se quitará el contenido visualmente, por lo que los vínculos serán invisibles, pero se podrá acceder a ellos con el teclado, lo que sería confuso y frustrante. Si usas visibility o display, se oculta visualmente y se vuelve inaccesible, por lo que se oculta para todos los usuarios.

Consulta el Paso 6: Oculta la lista.

Cómo animar la lista

Si te preguntas por qué usar visibility: hidden; en lugar de display: none;, es porque puedes animar la visibilidad. Solo tiene dos estados, hidden y visible, pero puedes combinarlo con otra propiedad, como transform o opacity, para crear un efecto de deslizamiento o de aparición gradual. Eso no funcionaría con display: none porque la propiedad display no se puede animar.

El siguiente CSS realiza la transición de opacity para crear un efecto de aparición y desaparición gradual.

ul {
  transition: opacity 0.6s linear, visibility 0.3s linear;
  visibility: var(--nav-list-visibility, visible);
}

[aria-expanded="false"] + ul {
  opacity: 0;
  visibility: var(--nav-list-visibility, hidden);
}

Si, en cambio, quieres animar el movimiento, considera unir la propiedad transition en una consulta de medios prefers-reduced-motion, ya que las animaciones pueden provocar náuseas, mareos y dolores de cabeza en algunos usuarios.

ul {
  visibility: var(--nav-list-visibility, visible);
}

@media (prefers-reduced-motion: no-preference) {
  ul {
    transition: transform 0.6s cubic-bezier(.68,-0.55,.27,1.55), visibility 0.3s linear;
  }
}

[aria-expanded="false"] + ul {
  transform: var(--nav-list-transform, translateX(100%));
  visibility: var(--nav-list-visibility, hidden);
}

Esto garantiza que solo las personas que no tienen preferencia por el movimiento reducido vean la animación.

Consulta el paso 7: Animación de la lista en CodePen.

Mejora el diseño del foco

Los usuarios que navegan con el teclado dependen de los estilos de enfoque de los elementos para orientarse y navegar en una página. Los estilos de enfoque predeterminados son mejores que no tenerlos (lo que sucede si configuras outline: none), pero tener estilos de enfoque personalizados más visibles mejora la experiencia del usuario.

Así es como se ven los estilos de enfoque predeterminados en el vínculo en Chrome 103.

Un contorno azul de 2 px alrededor de un vínculo enfocado en Chrome 103.

Puedes mejorar eso proporcionando tus propios estilos con tus propios colores. Si usas :focus-visible en lugar de :focus, permites que el navegador decida cuándo es apropiado mostrar los estilos de enfoque. Los estilos de :focus serán visibles para todos los usuarios de mouse, teclado y pantalla táctil, sin importar si los necesitan o no. Con :focus-visible, el navegador usa heurísticas internas para decidir si los muestra solo a los usuarios de teclado o a todos.

/* Remove the default :focus outline */
*:focus {
  outline: none;
}

/* Show a custom outline on :focus-visible */
*:focus-visible {
  outline: 2px solid var(--color-shades-dark);
  outline-offset: 4px;
}

Compatibilidad de navegadores con :focus-visible

Browser Support

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 85.
  • Safari: 15.4.

Source

Contorno oscuro de 2 px claramente visible con espaciado en el interior.

Existen diferentes maneras de destacar los elementos cuando se enfocan. Se recomienda usar la propiedad outline porque no interrumpe el diseño, lo que podría suceder con border, y funciona bien con el modo de contraste alto en Windows. Las propiedades que no funcionan bien son background-color o box-shadow, ya que es posible que no se muestren con la configuración de contraste personalizada.

Un sitio con un fondo oscuro y el enfoque destacado en púrpura.
Consulta el paso 8: Mejora los estilos de enfoque en CodePen.

¡Felicitaciones! Creaste una navegación principal con mejora progresiva, semánticamente enriquecida, accesible y optimizada para dispositivos móviles.

Siempre hay algo que se puede mejorar, por ejemplo:

  • Puedes considerar atrapar el enfoque dentro de la navegación o hacer que el resto de la página sea inerte en viewports estrechos.
  • Puedes agregar un vínculo de navegación en la parte superior de la página para permitir que los usuarios que usan el teclado omitan la navegación.

Si recuerdas cómo comenzó este artículo, con el objetivo de que la solución "no sea demasiado simple ni demasiado complicada", ahí es donde estamos ahora. Sin embargo, es posible que se complique demasiado la navegación.

Hay una diferencia clara entre las navegaciones y los menús. Las navegaciones son colecciones de vínculos para navegar por documentos relacionados. Los menús son colecciones de acciones que se pueden realizar en un documento. A veces, estas tareas se superponen. Es posible que tengas una navegación que también incluya un botón que realice una acción, como abrir una ventana modal, o que tengas un menú en el que una acción sea navegar a otra página, como una página de ayuda. Cuando ese sea el caso, es importante que no mezcles los roles de ARIA, sino que identifiques el propósito principal de tu componente y elijas el lenguaje de marcado y los roles según corresponda.

El elemento <nav> tiene un rol de navegación de ARIA implícito que es suficiente para comunicar que el elemento es una navegación, pero a menudo ves que los sitios también usan menu, menubar y menuitem. Como a veces usamos estos términos de forma indistinta, pensar que combinarlos para mejorar la experiencia de los usuarios de lectores de pantalla podría tener sentido. Antes de aprender por qué no suele ser así, veamos la definición oficial de estos roles.

El rol de navegación

Es una colección de elementos de navegación (por lo general, vínculos) para navegar por el documento o los documentos relacionados.

navigation (role) WAI-ARIA 1.1

El rol de menú

Un menú suele ser una lista de acciones o funciones comunes que el usuario puede invocar. El rol de menú es apropiado cuando se presenta una lista de elementos de menú de manera similar a un menú en una aplicación de escritorio.

menu (role) WAI-ARIA 1.1

El rol menubar

Es una presentación de menú que suele permanecer visible y se presenta de forma horizontal. El rol menubar se usa para crear una barra de menú similar a las que se encuentran en las aplicaciones de escritorio de Windows, Mac y Gnome. La barra de menú se usa para crear un conjunto coherente de comandos de uso frecuente. Los autores deben asegurarse de que la interacción con la barra de menú sea similar a la interacción típica con la barra de menú en una interfaz gráfica de usuario de escritorio.

menubar (role) WAI-ARIA 1.1

El rol menuitem

Es una opción en un conjunto de opciones que contiene un menú o una barra de menú.

menuitem (role) WAI-ARIA 1.1

La especificación es muy clara aquí: usa la navegación para navegar por el documento o los documentos relacionados, y el menú solo para una lista de acciones o funciones similares a los menús de las aplicaciones de escritorio. Si no estás creando el próximo Documentos de Google, es probable que no necesites ninguno de los roles de menú para la navegación principal.

¿Cuándo es apropiado usar un menú?

El uso principal de los elementos de menú no es la navegación, sino la realización de acciones. Supongamos que tienes una lista o tabla de datos, y los usuarios pueden realizar ciertas acciones en cada elemento de la lista. Podrías agregar un botón a cada fila y mostrar las acciones cuando los usuarios hagan clic en él.

<ul>
  <li>
    Product 1

    <button aria-expanded="false" aria-controls="options1">Edit</button>

    <div role="menu" id="options1">
      <button role="menuitem">
        Duplicate
      </button>
      <button role="menuitem">
        Delete
      </button>
      <button role="menuitem">
        Disable
      </button>
    </div>
  </li>
  <li>
    Product 2
    ...
  </li>
</ul>

Implicaciones de usar roles de menú

Es muy importante usar estos roles de menú con prudencia porque muchas cosas pueden salir mal.

Los menús esperan una estructura de DOM determinada. menuitem debe ser un elemento secundario directo de menu. El siguiente código podría romper el comportamiento semántico:

 <!-- Wrong, don't do this -->
<ul role="menu">
  <li>
    <a href="#" role="menuitem">Item 1</a>
  </li>
</ul>

Los usuarios expertos esperan que ciertas combinaciones de teclas funcionen con los menús y las barras de menú. Según la Guía de prácticas de creación de ARIA (APG), esto incluye lo siguiente:

  • Intro y barra espaciadora para seleccionar elementos del menú
  • Teclas de flecha en todas las direcciones para navegar entre los elementos
  • Las teclas Inicio y Fin para mover el foco al primer o último elemento, respectivamente.
  • a-z para mover el foco al siguiente elemento del menú con una etiqueta que comience con el carácter escrito.
  • Esc para cerrar el menú.

Si un lector de pantalla detecta un menú, el software podría cambiar automáticamente el modo de navegación, lo que permite usar los accesos directos mencionados anteriormente. Es posible que los usuarios de lectores de pantalla sin experiencia no puedan usar el menú porque no conocen estas combinaciones de teclas o no saben cómo usarlas.

Lo mismo ocurre con los usuarios de teclado, que podrían esperar poder usar Mayúsculas y Mayúsculas + Tab.

Hay mucho que considerar cuando creas menús y barras de menú, y lo primero que debes tener en cuenta es si es apropiado usarlos. Cuando creas un sitio web típico, el elemento nav con una lista y vínculos es todo lo que necesitas. Esto también incluye las aplicaciones de una sola página (SPA) o las apps web. La pila subyacente no importa. A menos que estés creando algo muy similar a una aplicación de escritorio, evita los roles de menú.

Recursos adicionales