Criar a navegação principal de um site

Este tutorial descreve como criar uma navegação principal acessível de um site. Você aprenderá sobre HTML semântico, acessibilidade e como o uso de atributos ARIA às vezes pode ser mais prejudicial do que vantajoso.

Manuel Matuzovijk
Manuel Matuzovify

Há muitas maneiras diferentes de criar a navegação principal de um site, em termos de estilo, funcionalidade e marcação e informações semânticas subjacentes. Se a implementação for muito minimalista, ela vai funcionar para a maioria das pessoas, mas a experiência do usuário (UX) talvez não seja boa. Se ela for projetada em excesso, poderá confundir os usuários ou até impedir que eles acessem o recurso.

Para a maioria dos sites, o ideal é criar algo que não seja muito simples nem muito complicado.

Como criar camada por camada

Neste tutorial, você começa com uma configuração básica e adiciona elementos camada por camada até fornecer informações, estilo e funcionalidade suficientes para agradar a maioria dos usuários. Para isso, use o princípio de aprimoramento progressivo, que afirma que você começa com a solução mais fundamental e robusta e adiciona camadas de funcionalidade aos poucos. Se uma camada não funcionar por algum motivo, a navegação ainda vai funcionar porque ela retorna à camada subjacente.

Estrutura básica

Para uma navegação básica, você precisa de duas coisas: elementos <a> e algumas linhas de CSS para melhorar o estilo e o layout padrão dos seus links.

<a href="/home">Home</a>
<a href="/about-us">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* 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);
}
Consulte a Etapa 1: HTML e CSS básicos" no CodePen.

Isso funciona bem para a maioria dos usuários, independentemente de como eles acessam o site. A navegação pode ser acessada com mouse, teclado, touchscreen ou leitor de tela, mas há espaço para melhorias. Para melhorar a experiência, estenda esse padrão básico com mais funcionalidades e informações.

Veja o que você pode fazer:

  • Destaque a página ativa.
  • Anunciar o número de itens aos usuários do leitor de tela.
  • Adicione um ponto de referência e permita que usuários de leitores de tela acessem a navegação diretamente usando um atalho.
  • Ocultar a navegação em janelas de visualização estreitas.
  • Melhorar o estilo do foco.

Destacar a página ativa

Para destacar a página ativa, adicione uma turma ao link correspondente.

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

O problema com essa abordagem é que ela transmite as informações de qual link está ativo puramente visualmente. Um usuário de leitor de tela cego não conseguia distinguir entre a página ativa e as outras. Felizmente, o padrão Accessible Rich Internet Applications (ARIA) também oferece uma maneira de comunicar essas informações semanticamente. Use o atributo e o valor aria-current="page" em vez de uma classe.

aria-current (estado) indica o elemento que representa o item atual dentro de um contêiner ou conjunto de elementos relacionados. Um token de página usado para indicar um link em um conjunto de links de paginação, em que o link é visualmente estilizado para representar a página exibida no momento. [Accessible Rich Internet Applications (WAI-ARIA) 1.1](https://www.w3.org/TR/wai-aria/#aria-current)
(em inglês)

Com o atributo adicional, um leitor de tela agora anuncia algo como "página atual, link, Quem somos", em vez de apenas "link, Quem somos".

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

Um efeito colateral conveniente é que você pode usar o atributo para selecionar o link ativo no CSS, tornando a classe active-page 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);
}
Consulte a Etapa 2: destacar a página ativa no CodePen.

Anunciar o número de itens

Olhando para a navegação, os usuários que enxergam sabem que ela contém apenas quatro links. Um usuário de leitor de tela cega não consegue obter essas informações tão rapidamente. Talvez seja necessário percorrer toda a lista de links. Isso pode não ser um problema se a lista for curta como neste exemplo, mas se tiver 40 links, essa tarefa pode ser complicada. Se um usuário de leitor de tela souber antecipadamente que a navegação contém muitos links, ele poderá decidir usar uma maneira diferente e mais eficiente de navegação, como a pesquisa no site.
Uma boa maneira de comunicar o número de itens no início é unir cada link em um item da lista (<li>) aninhado em uma lista não ordenada (<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>

Quando um usuário do leitor de tela encontrar a lista, o software anunciará algo como "lista, 4 itens".

Esta é uma demonstração da navegação usada com o leitor de tela NVDA no Windows.

Agora você precisa adaptar o estilo para ficar 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;
}

O uso de listas pode ter muitas vantagens para usuários de leitores de tela:

  • Eles podem conferir o número total de itens antes de interagir com eles.
  • Eles podem usar atalhos para pular de um item a outro.
  • Eles podem usar atalhos para pular de uma lista para outra.
  • O leitor de tela pode anunciar o índice do item atual (por exemplo, "item da lista, dois de quatro").

Além disso, se a página não tiver CSS, a lista vai mostrar os links como um grupo coerente de itens, em vez de apenas uma pilha de links.

Um detalhe importante sobre o VoiceOver no Safari é que você perde todas essas vantagens ao definir list-style: none. Isso ocorre por design. A equipe do WebKit decidiu remover a semântica de lista quando ela não se parece com uma lista. Dependendo da complexidade da navegação, isso pode ou não ser um problema. Por um lado, a navegação ainda pode ser usada e afeta apenas o VoiceOver no Safari. O VoiceOver com Chrome ou Firefox ainda anuncia o número de itens, além de outros leitores de tela, como o NVDA. Por outro lado, as informações semânticas podem ser realmente úteis em algumas situações. Para tomar essa decisão, você deve testar a navegação com usuários reais de leitores de tela e receber o feedback deles. Se você decidir que precisa que o VoiceOver no Safari se comporte como todos os outros leitores de tela, é possível contornar o problema definindo a função da lista ARIA explicitamente em <ul>. Isso reverte o comportamento para o estado anterior à remoção do estilo da lista. Visualmente, a lista ainda é a mesma.

<ul role="list">
  <li>
     <a href="/home">Home</a>
  </li>
  ...
</ul>
Consulte a Etapa 3: anunciar o número de itens no CodePen.

Adicionar um ponto turístico

Com pouco esforço, você fez grandes melhorias para usuários de leitores de tela, mas ainda há mais uma coisa que você pode fazer. A navegação é semanticamente apenas uma lista de links, e é difícil dizer que essa lista específica é a navegação principal do seu site. Para transformar essa lista comum em uma lista de navegação, una o <ul> em um elemento <nav>.

O uso do elemento <nav> tem várias vantagens. É importante ressaltar que um leitor de tela anuncia algo como "navegação", quando o usuário interage com ele, e adiciona um ponto de referência à página. Pontos de referência são regiões especiais na página, como <header>, <footer> ou <main>, para onde um leitor de tela pode pular. Ter pontos de referência em uma página pode ser útil, porque permite que os usuários de leitores de tela acessem regiões importantes diretamente, sem precisar interagir com o restante da página. Por exemplo, é possível ir de um ponto a outro pressionando a tecla D no NVDA. Na narração, é possível usar o rotor para listar todos os pontos de referência na página pressionando VO + U.

Uma lista de quatro pontos de referência: banner, navegação, principal e informações de conteúdo.
Rotor no VoiceOver listando todos os pontos de referência em uma página.

Nesta lista, há quatro pontos de referência: banner, que é o elemento <header>, navegação é o <nav>, main é o elemento <main> e informações de conteúdo são <footer>. Essa lista não deve ser muito longa. Você só deve marcar partes importantes da sua interface do usuário como pontos de referência, como a pesquisa no site, uma navegação local ou uma paginação.

Se você tiver uma navegação em todo o site, uma navegação local para a página e uma paginação em uma única página, também é possível ter três elementos <nav>. Tudo bem, mas agora há três pontos de referência de navegação e semanticamente todos são iguais. É difícil diferenciá-los, a menos que você conheça muito bem a estrutura da página.

Imagem mostrando três pontos de referência em que todos dizem &quot;navegação&quot;.
O rotor no VoiceOver listando três pontos de referência de navegação sem rótulos.

Para torná-las distinguíveis, rotule-as usando aria-labelledby ou 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>

Se o rótulo escolhido já existir em algum lugar da página, use aria-labelledby e faça referência ao rótulo existente usando o 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>

Um rótulo conciso é suficiente, não fique muito prolixo. Omita expressões como "navegação" ou "menu", porque o leitor de tela já fornece essas informações aos usuários.

Pontos de referência
VoiceOver listando os pontos de referência "banner", "navegação principal", "main", "navegação na página", "selecionar navegação na página" e "informações de conteúdo".
Consulte a Etapa 4: adicionar um ponto de referência no CodePen.

Ocultar a navegação em janelas de visualização estreitas

Pessoalmente, não gosto muito de ocultar a navegação principal em janelas de visualização estreitas, mas se a lista de links for muito longa, não há como evitar. Se esse for o caso, em vez da lista, os usuários verão um botão com o rótulo "Menu", um ícone de hambúrguer ou uma combinação. Clicar no botão mostra e oculta a lista. Se você tem conhecimento básico de JavaScript e CSS, essa é uma tarefa viável, mas há várias coisas em termos de UX e acessibilidade que você precisa cuidar.

  • Você precisa ocultar a lista de maneira acessível.
  • A navegação precisa ser acessível pelo teclado.
  • A navegação precisa informar se está ou não visível.

Adicionar um botão de hambúrguer

Como você está seguindo o princípio de aprimoramento progressivo, é importante garantir que a navegação ainda funcione e faça sentido mesmo com o JavaScript desativado.
A primeira coisa que sua navegação precisa é um botão de hambúrguer. Você o cria em HTML em um elemento de modelo, clona em JavaScript e adiciona à navegação.

Uma página com um botão de hambúrguer.
Resultado: em vez de links, a navegação mostra um botão de hambúrguer em janelas de visualização estreitas.
<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. O atributo aria-expanded informa ao software leitor de tela se o elemento que o botão controla está ou não expandido.
  2. aria-label dá ao botão um chamado nome acessível, uma alternativa de texto para o ícone de hambúrguer.
  3. Você oculta <svg> da tecnologia adaptativa usando aria-hidden porque ela já tem um rótulo de texto fornecido por aria-label.
  4. O aria-controls informa à tecnologia adaptativa que tem suporte ao atributo (por exemplo, JAWS), que é o elemento controlado pelo botão.
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. É conveniente para os usuários poder fechar a navegação sempre que quiserem, por exemplo, pressionando a tecla Esc.
  2. É importante usar insertBefore em vez de appendChild porque o botão precisa ser o primeiro elemento da navegação. Se um usuário de teclado ou leitor de tela pressionar Tab depois de clicar no botão, ele espera focar o primeiro item da lista. Se o botão vier após a lista, esse não será o caso.

Em seguida, redefina o estilo padrão do botão e assegure que ele só fique visível em janelas de visualização estreitas.

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

/* Reset button styling */
button {
  all: unset;
  display: var(--nav-button-display, flex);
}
Confira a Etapa 5: adicionar um botão de navegação no CodePen.

Ocultando a lista

Antes de ocultar a lista, posicione e estilize a navegação e a lista para que o layout seja otimizado para janelas de visualização estreitas, mas tenha uma boa aparência em telas maiores.
Primeiro, remova a <nav> do fluxo natural da página e coloque-a no canto superior da janela de visualização.

@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;
}

Em seguida, altere o layout em janelas de visualização estreitas adicionando uma nova propriedade personalizada (—-nav-list-layout). O layout é em colunas por padrão e muda para linha em telas maiores.

@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;
}

A navegação será parecida com esta em janelas de visualização estreitas.

A página mostrando a lista de navegação e o botão de hambúrguer.
O botão de hambúrguer e a lista são colocados no canto superior da janela de visualização.

A lista obviamente precisa de CSS. Vamos mover a barra para o canto superior, fazer com que ela preencha toda a tela verticalmente, aplicar uma background-color e uma 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;
}

A lista deve ter esta aparência em janelas de visualização estreitas, mais parecida com uma barra lateral do que com uma lista simples.

A lista de navegação é aberta.

Por fim, oculte a lista, mostre-a apenas quando o usuário clicar no botão uma vez e oculte-a quando ele clicar novamente. É importante ocultar apenas a lista e não a navegação inteira, porque ocultar a navegação também significa ocultar um ponto de referência importante.

Anteriormente, você adicionou um evento de clique ao botão para alternar o valor do atributo aria-expanded. Use essas informações como uma condição para mostrar e ocultar a lista no 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);
}

É importante usar uma declaração de propriedade como visibility: hidden ou display: none em vez de opacity: 0 ou translateX(100%) para ocultar a lista. Essas propriedades garantem que os links não sejam focalizáveis quando a navegação estiver oculta. O uso de opacity ou translate removerá o conteúdo visualmente. Assim, os links ficariam invisíveis e ainda acessíveis pelo teclado, o que seria confuso e frustrante. O uso de visibility ou display oculta a visualização e faz com que ela fique inacessível, ocultando-a para todos os usuários.

Consulte a Etapa 6: ocultar a lista.

Como animar a lista

Se você está se perguntando por que usar visibility: hidden; em vez de display: none;, é porque você pode animar a visibilidade. Ele tem apenas dois estados, hidden e visible, mas é possível combiná-lo com outra propriedade, como transform ou opacity, para criar um efeito de deslizar ou de aparecimento gradual. Isso não funcionaria com display: none porque a propriedade display não é animável.

O CSS a seguir faz a transição de opacity para criar um efeito de aparecimento gradual e esmaecimento.

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);
}

Se, em vez disso, você quiser animar o movimento, considere unir a propriedade transition em uma consulta de mídia prefered-reduced-motion, porque as animações podem causar náuseas, tonturas e dores de cabeça em alguns usuários.

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);
}

Isso garante que apenas as pessoas que não têm preferência por movimento reduzido verão a animação.

Consulte a Etapa 7: animar a lista no CodePen.

Melhorar o estilo do foco

Os usuários de teclado dependem dos estilos de foco dos elementos para orientação e navegação em uma página. Os estilos de foco padrão são melhores do que nenhum estilo de foco, o que acontece se você definir outline: none. No entanto, ter estilos de foco personalizados mais claramente visíveis melhora a experiência do usuário.

Veja como são os estilos de foco padrão do link no Chrome 103.

Um contorno azul de 2 px ao redor de um link focado no Chrome 103.

É possível melhorar isso fornecendo seus próprios estilos com suas próprias cores. Ao usar :focus-visible em vez de :focus, você permite que o navegador decida quando é apropriado mostrar estilos de foco. Os estilos :focus vão ficar visíveis para todos os usuários e usuários de mouse, teclado e toque, independente de eles precisarem deles ou não. Com :focus-visible, o navegador usa heurística interna para decidir se eles serão exibidos apenas para os usuários do teclado ou para 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;
}

Suporte do navegador para :focus-visible

Compatibilidade com navegadores

  • 86
  • 86
  • 85
  • 15,4

Origem

Contorno escuro de 2 px claramente visível com espaçamento interno.

Há diferentes maneiras de destacar itens quando eles estão focados. Recomendamos o uso da propriedade outline porque ela não corrompe o layout, o que pode acontecer com o border, e funciona bem com o modo de alto contraste no Windows. As propriedades que não funcionam bem são background-color ou box-shadow, porque podem não ser exibidas com configurações de contraste personalizadas.

Um site com um plano de fundo escuro com o foco destacado em roxo.
Confira a Etapa 8: melhorar os estilos de foco no CodePen.

Parabéns! Você criou uma navegação principal progressivamente aprimorada, semanticamente rica, acessível e compatível com dispositivos móveis.

Sempre há algo que pode ser melhorado, por exemplo:

  • Você pode considerar interromper o foco na navegação ou tornar o restante da página inerte em janelas de visualização estreitas.
  • Você pode adicionar um link de salto na parte de cima da página para permitir que os usuários do teclado pulem a navegação.

Se você se lembra de como este artigo começou, com o objetivo de que a solução "não seja simples nem complicada demais", é aqui que estamos agora. No entanto, é possível sobrecarregar uma navegação.

Há uma diferença clara entre navegações e menus. As navegações são coleções de links para acessar documentos relacionados. Menus são coleções de ações a serem realizadas em um documento. Às vezes, essas tarefas se sobrepõem. Você pode ter uma navegação que também inclui um botão que realiza uma ação, como abrir uma janela modal, ou pode ter um menu em que uma ação navega para outra página, como uma página de ajuda. Quando esse for o caso, é importante não misturar os papéis ARIA, mas identificar o objetivo principal do seu componente e escolher a marcação e os papéis de acordo.

O elemento <nav> tem uma função implícita ARIA de navegação, que é suficiente para comunicar que o elemento é uma navegação, mas muitas vezes os sites também usam menu, barra de menu e item de menu. Como às vezes usamos esses termos como sinônimos, fazer sentido combiná-los para melhorar a experiência dos usuários de leitores de tela. Antes de saber por que isso não acontece, vamos conferir a definição oficial desses papéis.

Papel de navegação

Um conjunto de elementos de navegação (geralmente links) para navegar pelo documento ou documentos relacionados.

navegação (função) WAI-ARIA 1.1

Função de menu

Um menu geralmente é uma lista de ações ou funções comuns que o usuário pode invocar. A função do menu é apropriada quando uma lista de itens de menu é apresentada de maneira semelhante a um menu em um aplicativo para computador.

menu (função) WAI-ARIA 1.1

O papel da barra de menus

Uma apresentação de menu que geralmente permanece visível e geralmente é apresentada horizontalmente. A função da barra de menus é usada para criar uma barra de menus semelhante àquelas encontradas nos aplicativos de desktop Windows, Mac e Gnome. Uma barra de menu é usada para criar um conjunto consistente de comandos usados com frequência. Os autores devem garantir que a interação da barra de menus seja semelhante à interação típica da barra de menus em uma interface gráfica do usuário para computadores.

barra de menus (função) WAI-ARIA 1.1

Papel menuitem

Uma opção em um conjunto de opções contido por um menu ou uma barra de menus.

menuitem (papel) WAI-ARIA 1.1

A especificação é muito clara aqui. Use a navegação para navegar pelo documento ou documentos relacionados e o menu apenas para obter uma lista de ações ou funções semelhantes aos menus em aplicativos de desktop. Se você não estiver criando o próximo documento Google, provavelmente não precisa das funções de menu para a navegação principal.

Quando um cardápio é adequado?

O uso principal dos itens de menu não é a navegação, mas sim para realizar ações. Digamos que você tenha uma lista ou tabela de dados e que os usuários possam realizar determinadas ações em cada item da lista. Você pode adicionar um botão a cada linha e mostrar as ações quando os usuários clicarem no botão.

<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>

Implicações do uso de papéis de menu

É muito importante usar essas funções de menu com sabedoria, porque muita coisa pode dar errado.

Os menus esperam uma determinada estrutura DOM. menuitem precisa ser um item filho direto de menu. O código a seguir pode corromper o comportamento semântico:

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

Usuários experientes esperam que certos atalhos de teclado funcionem com menus e barras de menu. De acordo com o Guia de práticas de criação ARIA (APG, na sigla em inglês), isso inclui:

  • Pressione Enter e espaço para selecionar os itens do menu.
  • Teclas de seta em todas as direções para navegar entre os itens.
  • Use as teclas Home e End para mover o foco para o primeiro ou o último item, respectivamente.
  • de a a z para mover o foco para o próximo item de menu com um rótulo que comece com o caractere digitado.
  • Esc para fechar o menu.

Se um leitor de tela detectar um menu, o software poderá mudar automaticamente o modo de navegação, permitindo o uso dos atalhos mencionados anteriormente. Usuários inexperientes de leitores de tela podem não conseguir usar o menu porque não conhecem esses atalhos ou não sabem como usá-los.

O mesmo acontece com os usuários de teclado que talvez esperem usar Shift e Shift + Tab.

Há muito a considerar ao criar menus e barras de menu: determinar se é apropriado usá-los primeiro. Ao criar um site comum, você só precisa de um elemento de navegação com uma lista e links. Isso também inclui aplicativos de página única (SPA, na sigla em inglês) ou apps da Web. A pilha subjacente não importa. A menos que você esteja criando algo muito próximo a um aplicativo de computador, evite funções de menu.

Outros recursos

Imagem principal por Mick Haupt