Criar a navegação principal de um site

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

Manuel Matuzović
Manuel Matuzović

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) pode não ser ótima. Se houver excesso de engenharia, isso pode confundir os usuários ou até mesmo impedi-los de acessá-lo.

Para a maioria dos sites, você quer criar algo que não seja nem muito simples nem muito complicado.

Como criar camada por camada

Neste tutorial, você começa com uma configuração básica e adiciona recursos camada por camada até fornecer apenas as informações, o estilo e a funcionalidade suficientes para agradar a maioria dos usuários. Para isso, você usa o princípio de aprimoramento progressivo, que determina que você começa com a solução mais fundamental e robusta e adiciona camadas de funcionalidade progressivamente. Se uma camada falhar por algum motivo, a navegação ainda vai funcionar porque ela voltará suavemente para a camada abaixo.

Estrutura básica

Para uma navegação básica, você precisa de dois 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);
}
Confira a Etapa 1: HTML e CSS básicos" no CodePen.

Isso funciona bem para a maioria dos usuários, independentemente de como eles acessem o site. A navegação é acessível com um mouse, um teclado, um dispositivo touchscreen ou um leitor de tela, mas há espaço para melhorias. É possível melhorar a experiência ampliando 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 para usuários de leitores de tela.
  • Adicione um ponto de referência e permita que os usuários de leitores de tela acessem a navegação diretamente usando um atalho.
  • Ocultar a navegação em viewports estreitas.
  • Melhore o estilo de foco.

Destacar a página ativa

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

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

O problema dessa abordagem é que ela transmite informações com links ativos puramente visuais. Um usuário com leitor de tela cego não consegue diferenciar a página ativa das outras. Felizmente, o padrão Acessible Rich Internet Applications (ARIA) oferece uma maneira de comunicar essas informações semanticamente. Use o atributo e o valor aria-current=&quot;page&quot; em vez de uma classe.

aria-current (estado) indica o elemento que representa o item atual em 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 estilo do link é visualmente 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, Sobre nós" em vez de apenas "link, Sobre nós".

<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);
}
Confira Etapa 2: destacar a página ativa no CodePen.

Anunciar o número de itens

Ao olhar para a navegação, os usuários com visão podem dizer que ela contém apenas quatro links. Um usuário cego com leitor de tela não consegue essas informações tão rapidamente. Talvez seja necessário percorrer toda a lista de links. Isso não será um problema se a lista for curta, como neste exemplo, mas se ela tiver 40 links, essa tarefa pode ser trabalhosa. Se um usuário de leitor de tela souber de antemão que a navegação contém muitos links, ele poderá decidir usar uma forma de navegação diferente e mais eficiente, como a pesquisa do site.
Uma boa maneira de comunicar o número de itens com antecedência é agrupar cada link em um item de 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 de leitor de tela encontra a lista, o software anuncia algo como "lista, 4 itens".

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

Agora, você precisa adaptar o estilo para que ele fique 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 os 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 da lista para 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 for apresentada sem 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 uma lista não se parece com uma lista. Dependendo da complexidade da navegação, isso pode ser um problema ou não. Por um lado, a navegação ainda pode ser usada e afeta apenas o VoiceOver no Safari. O VoiceOver com o Chrome ou o Firefox ainda anuncia o número de itens, assim como outros leitores de tela, como o NVDA. Por outro lado, as informações semânticas podem ser muito úteis em algumas situações. Para tomar essa decisão, teste a navegação com usuários reais de leitores de tela e receba feedback deles. Se você precisar que o VoiceOver no Safari se comporte como todos os outros leitores de tela, defina o papel da lista ARIA explicitamente no <ul>. Isso reverte o comportamento para o estado antes de você remover o estilo da lista. Visualmente, a lista ainda tem a mesma aparência.

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

Adicionar um ponto de referência

Com pouco esforço, você fez ótimas melhorias para usuários de leitores de tela, mas ainda há mais uma coisa que você pode fazer. A navegação semanticamente ainda é 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, envolva o <ul> em um elemento <nav>.

O uso do elemento <nav> tem várias vantagens. Um leitor de tela anuncia algo como "navegação", quando o usuário interage com ele, e adiciona um marco à página. Os pontos de referência são regiões especiais na página, como <header>, <footer> ou <main>, para as quais um leitor de tela pode pular. Ter pontos de referência em uma página pode ser útil, porque permite que usuários de leitores de tela acessem regiões importantes diretamente na página, sem precisar interagir com o restante da página. Por exemplo, você pode pular de um ponto de referência para outro pressionando a tecla D no NVDA. No VoiceOver, você pode usar o rotor para listar todos os marcos 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.

Nessa lista, são mostrados quatro pontos de referência: banner, que é o elemento <header>; navigation é o <nav>; main: o elemento <main> e content information é o <footer>. Essa lista não precisa ser muito longa. Marque apenas as partes essenciais da interface 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 poderá ter três elementos <nav>. Tudo bem, mas agora há três pontos de referência de navegação e, semanticamente, todos parecem 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 com o texto &quot;navegação&quot;.
O rotor do VoiceOver listando três pontos de referência de navegação sem rótulos.

Para distingui-los, use 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, você poderá usar aria-labelledby e fazer 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 use muitas palavras. 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", "principal", "navegação de página", "selecionar navegação de página" e "informações do conteúdo".
Consulte a Etapa 4: como adicionar um ponto de referência no CodePen.

Ocultar a navegação em viewports estreitas

Pessoalmente, não gosto muito de ocultar a navegação principal em janelas de visualização estreitas, mas se a lista de links ficar muito longa, não haverá como contornar. Nesse caso, em vez da lista, os usuários vão encontrar um botão "Menu" ou um ícone de hambúrguer ou uma combinação dos dois. Ao clicar no botão, a lista é exibida e oculta. Se você conhece JavaScript e CSS básicos, essa é uma tarefa possível, mas há várias coisas em termos de UX e acessibilidade que você precisa cuidar.

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

Adicionando um botão de hambúrguer

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

Uma página mostrando um botão de navegação.
Resultado: em vez de links, a navegação mostra um botão de hambúrguer em visualizações 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 do leitor de tela se o elemento controlado pelo botão está aberto ou não.
  2. aria-label atribui ao botão um nome acessível, uma alternativa de texto para o ícone de hambúrguer.
  3. Você oculta o <svg> da tecnologia assistiva usando aria-hidden porque ele já tem um rótulo de texto fornecido por aria-label.
  4. aria-controls informa à tecnologia adaptativa, que oferece suporte ao atributo (por exemplo, JAWS), qual elemento o botão controla.
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 poderem 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 no primeiro item da lista. Se o botão estiver depois da lista, esse não será o caso.

Em seguida, você vai redefinir o estilo padrão do botão e garantir que ele só apareça em visualizações 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.

Como ocultar a lista

Antes de ocultar a lista, posicione e estilize a navegação e a lista para que o layout seja otimizado para visualizações estreitas, mas ainda fique bom em telas maiores.
Primeiro, remova o <nav> do fluxo natural da página e coloque-o no canto superior da 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;
}

Em seguida, mude o layout em janelas de visualização estreitas adicionando uma nova propriedade personalizada (—-nav-list-layout). O layout é uma coluna por padrão e muda para uma 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á semelhante a esta em janelas de visualização estreitas.

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

A lista obviamente precisa de CSS. Vamos movê-lo para o canto superior, fazer com que ele preencha toda a tela verticalmente, aplicar um background-color e um 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 ser semelhante a esta em janelas de visualização estreitas, mais como uma barra lateral do que uma lista simples.

A lista de navegação aberta.

Por fim, oculte a lista, mostrando-a apenas quando o usuário clicar no botão uma vez e ocultando-a quando ele clicar novamente. É importante ocultar apenas a lista, e não toda a navegação, 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. Você pode usar 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 focalizados quando a navegação estiver oculta. Usar opacity ou translate vai remover o conteúdo visualmente para que os links fiquem invisíveis, mas ainda possam ser acessados usando o teclado, o que seria confuso e frustrante. O uso de visibility ou display oculta o elemento visualmente e o torna inacessível, ou seja, oculto para todos os usuários.

Confira Etapa 6: como ocultar a lista.

Como animar a lista

Se você está se perguntando por que usar visibility: hidden; em vez de display: none;, é porque é possível animar a visibilidade. Ela tem apenas dois estados, hidden e visible, mas é possível combiná-lo com outra propriedade, como transform ou opacity, para criar um efeito deslizante ou de esmaecimento. Isso não funciona com display: none porque a propriedade de exibição não é animada.

As transições CSS a seguir opacity para criar um efeito de desbotamento.

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 você quiser animar o movimento, considere agrupar a propriedade transition em uma consulta de mídia prefers-reduced-motion, porque as animações podem causar náusea, tontura 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 vão ver a animação.

Confira Etapa 7: animar a lista no CodePen.

Melhorar o estilo de 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 não ter estilos de foco (o que acontece se você definir outline: none), mas ter estilos de foco personalizados mais visíveis melhora a experiência do usuário.

Confira como os estilos de foco padrão no link ficam no Chrome 103.

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

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

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

Origem

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

Há maneiras diferentes de destacar itens quando eles estão em foco. O uso da propriedade outline é recomendado porque ela não interrompe o layout, o que pode acontecer com 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 elas podem não aparecer com configurações de contraste personalizadas.

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

Parabéns! Você criou uma navegação principal aprimorada progressivamente, rica em semântica, acessível e otimizada para dispositivos móveis.

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

  • Você pode prender o foco na navegação ou tornar o restante da página inativo em visualizações estreitas.
  • É possível adicionar um link de pular 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 fosse "nem muito simples nem muito complicada", é isso que estamos fazendo agora. No entanto, a navegação pode ser engenhosa demais.

Há uma diferença clara entre navegações e menus. As navegações são coleções de links para navegar em documentos relacionados. Os 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 executa uma ação, como abrir uma janela modal, ou um menu em que uma ação é navegar para outra página, como uma página de ajuda. Nesse caso, é importante não misturar as funções ARIA, mas identificar o objetivo principal do componente e escolher a marcação e as funções de acordo com isso.

O elemento <nav> tem uma função ARIA implícita 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 de forma intercambiável, pode fazer sentido combiná-los para melhorar a experiência dos usuários de leitores de tela. Antes de saber por que isso geralmente não acontece, vamos conferir a definição oficial dessas funções.

Função de navegação

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

navigation (papel) WAI-ARIA 1.1

A função do menu

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

menu (role) WAI-ARIA 1.1

Função da barra de menus

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

menubar (role) WAI-ARIA 1.1

O papel de item de menu

Uma opção em um conjunto de escolhas contido em um menu ou menubar.

menuitem (role) 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 uma lista de ações ou funções semelhantes aos menus em aplicativos para computador. Se você não estiver criando o próximo Google Docs, provavelmente não vai precisar de nenhuma das funções de menu para a navegação principal.

Quando um cardápio é apropriado?

O principal uso 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 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 nele.

<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 funções de menu

É muito importante usar essas funções de menu com sabedoria, porque muitas coisas podem dar errado.

Os menus esperam uma determinada estrutura de DOM. menuitem precisa ser um item filho direto de menu. O código a seguir pode interromper 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 determinados atalhos do teclado funcionem com menus e barras de menus. Com base no Guia de práticas de criação de ARIA (APG, na sigla em inglês), isso inclui:

  • Enter e espaço para selecionar itens de menu.
  • Teclas de seta em todas as direções para navegar entre os itens.
  • As teclas Home e End para mover o foco para o primeiro ou o último item, respectivamente.
  • a-z para mover o foco para o próximo item de menu com um rótulo que começa 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 de leitores de tela inexperientes podem não conseguir usar o menu porque não conhecem esses atalhos ou não sabem como usá-los.

O mesmo vale para usuários de teclado que esperam poder usar Shift e Shift + Tab.

Há muitas coisas a considerar ao criar menus e barras de menus, e a primeira delas é se é apropriado usá-los. Ao criar um site típico, o elemento de navegação com uma lista e links é tudo o que você precisa. Isso também inclui aplicativos de página única (SPA) ou apps da Web. A pilha subjacente não importa. A menos que você esteja criando algo muito próximo a um aplicativo para computador, evite as funções de menu.

Outros recursos

Imagem principal de Mick Haupt