Dev Tools & Workflow

Um guia para desenvolvedores sobre rótulos ARIA que realmente ajudam

Rótulos ARIA não são uma camada mágica de acessibilidade. Bem usados, tornam os controles compreensíveis. Usados de forma casual, escondem texto útil e criam interfaces confusas.

The Wux Webtools Team The Wux Webtools Team 9 min de leitura Assistido por IA, revisado por humanos
Illustration of a developer reviewing accessible labels and UI components on a screen.
Tabela de conteúdos
  1. Rótulos ARIA servem para nomes, não para desculpas
  2. O nome acessível, em inglês simples
  3. Primeira regra: prefira HTML nativo e rótulos visíveis
  4. Quando `aria-label` é a ferramenta certa
  5. Quando `aria-label` é a ferramenta errada
  6. Use `aria-labelledby` quando já houver texto visível
  7. Use `aria-describedby` para texto de ajuda, não para o nome
  8. Controles repetidos precisam de nomes únicos
  9. Não rotule tudo
  10. Verifique o nome calculado, não apenas o código
  11. Uma checklist prática de revisão
  12. A disciplina silenciosa de um bom ARIA

Rótulos ARIA servem para nomes, não para desculpas

ARIA é útil, mas muitas vezes é usado como remendo para HTML pouco claro. É aí que as equipes se complicam.

O exemplo mais comum é aria-label. Parece inofensivo: adicionar uma string, satisfazer um linter e seguir em frente. Mas um nome acessível não é decoração. É o nome que muitas tecnologias assistivas expõem aos usuários quando eles navegam por botões, links, campos de formulário, títulos, landmarks e controles.

Se esse nome for vago, duplicado, desatualizado ou diferente do rótulo visível, a interface fica mais difícil de usar. Às vezes, pior: aria-label pode sobrescrever um texto melhor que já estava presente no DOM.

O objetivo não é adicionar mais ARIA. O objetivo é tornar claros o nome, a função, o estado e a finalidade de cada elemento da interface.

O nome acessível, em inglês simples

A maioria dos elementos interativos tem um nome acessível. Leitores de tela usam esse nome para anunciar o que o elemento é.

Por exemplo:

<button>Save changes</button>

Um leitor de tela pode anunciar algo como: “Save changes, button.” A função vem do elemento button nativo. O nome vem do texto dentro dele.

Esse é o caso ideal: o texto visível e o nome acessível correspondem.

Atributos de rotulagem ARIA se tornam úteis quando a interface visível não fornece um nome completo, ou quando o nome precisa vir de outro elemento. Os principais atributos são:

  • aria-label: fornece uma string diretamente no elemento.
  • aria-labelledby: aponta para um ou mais elementos cujo texto se torna o nome.
  • aria-describedby: aponta para um texto de descrição complementar, não para o nome principal.

Esses três são relacionados, mas não intercambiáveis.

Primeira regra: prefira HTML nativo e rótulos visíveis

Se você puder colocar texto visível no controle, faça isso primeiro.

Isto é melhor:

<button>Delete invoice</button>

Do que isto:

<button aria-label="Delete invoice">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

O segundo padrão é válido para um botão somente com ícone. Mas, se o design puder tolerar texto visível, esse texto ajuda todo mundo: usuários de leitores de tela, usuários de reconhecimento de fala, pessoas sob carga cognitiva, pessoas fazendo uma varredura rápida e pessoas usando ferramentas de tradução.

Este é um tema recorrente no trabalho de acessibilidade. HTML nativo e affordances visíveis resolvem mais problemas do que metadados ocultos. O mesmo princípio se aplica à semântica de botões de forma mais ampla; se sua equipe está auditando controles de UI, nossa checklist para botões web acessíveis é um bom complemento para este guia.

Quando aria-label é a ferramenta certa

Use aria-label quando um elemento precisa de um nome acessível e não há texto visível adequado para referenciar.

O caso clássico é um botão somente com ícone:

<button aria-label="Search">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
    <!-- icon -->
  </svg>
</button>

Isso é razoável. O ícone visível sugere busca, mas o caminho SVG em si não fornece um nome confiável. O aria-label fornece um.

Outros bons casos incluem:

  • Um botão de fechar representado apenas por um “X”.
  • Um landmark de navegação que precisa de um nome mais específico, como aria-label="Product".
  • Um controle repetido em que o contexto visível não faz parte do texto do botão.

Por exemplo:

<nav aria-label="Primary">
  ...
</nav>

<nav aria-label="Footer">
  ...
</nav>

Ambos são landmarks de navegação, mas seus rótulos ajudam os usuários a distingui-los ao se moverem por landmarks.

Quando aria-label é a ferramenta errada

Não adicione aria-label só porque um teste diz que um elemento precisa de um rótulo. Corrija a marcação primeiro.

Ruim:

<div role="button" tabindex="0" aria-label="Submit">Submit</div>

Melhor:

<button>Submit</button>

O primeiro exemplo cria trabalho desnecessário. Agora você precisa recriar o comportamento de teclado, estados desabilitados, comportamento de formulário e expectativas que botões nativos já oferecem.

Também evite usar aria-label para renomear texto visível de uma forma que mude o significado.

<button aria-label="Delete invoice">Remove</button>

Isso parece pequeno, mas pode confundir usuários que dependem de entrada por fala. Se um botão visível diz “Remove”, mas seu nome acessível é “Delete invoice”, um usuário tentando dizer “click Remove” talvez não obtenha o resultado esperado. O requisito “label in name” da WCAG existe exatamente por esse motivo: o texto visível geralmente deve estar contido no nome acessível.

Uma versão melhor:

<button aria-label="Remove invoice">Remove</button>

Muitas vezes, melhor ainda:

<button>Remove invoice</button>

Use aria-labelledby quando já houver texto visível

Se o texto do rótulo já está na página, aria-labelledby geralmente é melhor do que aria-label.

Exemplo:

<h2 id="billing-title">Billing address</h2>
<section aria-labelledby="billing-title">
  ...
</section>

O nome acessível da seção agora vem do título visível. Você evita duplicar strings, o que reduz erros de tradução e rótulos desatualizados.

Isso é especialmente útil para grupos de formulário:

<fieldset aria-labelledby="shipping-speed-title">
  <legend id="shipping-speed-title">Shipping speed</legend>

  <label>
    <input type="radio" name="shipping" value="standard">
    Standard
  </label>

  <label>
    <input type="radio" name="shipping" value="express">
    Express
  </label>
</fieldset>

Em muitos casos, o legend nativo é suficiente sem ARIA. O ponto é que rótulos visíveis devem liderar. ARIA deve conectar significado existente, não criar uma segunda versão privada dele.

Use aria-describedby para texto de ajuda, não para o nome

Uma descrição não é um rótulo.

Considere este campo:

<label for="password">Password</label>
<input id="password" type="password" aria-describedby="password-help">
<p id="password-help">Use at least 12 characters.</p>

O nome acessível é “Password.” A descrição é “Use at least 12 characters.” Um leitor de tela pode anunciar ambos, mas eles servem a propósitos diferentes.

Não faça isto:

<input type="password" aria-label="Use at least 12 characters">

Isso nomeia o campo pela instrução, não pelo conceito. Um usuário navegando por um formulário quer saber primeiro o que é o campo e depois quais restrições se aplicam.

Essa distinção também importa em estados de erro:

<label for="email">Email</label>
<input
  id="email"
  type="email"
  aria-invalid="true"
  aria-describedby="email-error"
>
<p id="email-error">Enter an email address in the format [email protected].</p>

O rótulo permanece estável. A mensagem de erro se torna contexto complementar.

Controles repetidos precisam de nomes únicos

Listas e cards são onde rótulos ARIA muitas vezes se tornam necessários.

Ruim:

<button>Delete</button>
<button>Delete</button>
<button>Delete</button>

Um usuário de leitor de tela navegando por botões pode ouvir “Delete, button” três vezes sem contexto.

Bom:

<button aria-label="Delete report: Q4 revenue">Delete</button>
<button aria-label="Delete report: Hiring plan">Delete</button>
<button aria-label="Delete report: Vendor list">Delete</button>

Este é um uso legítimo de aria-label: o texto visível permanece conciso, enquanto o nome acessível inclui o objeto.

Mas use esse padrão com cuidado. Se o nome do objeto estiver visível por perto, aria-labelledby pode ser mais fácil de manter:

<article>
  <h3 id="report-q4">Q4 revenue</h3>
  <button aria-labelledby="delete-q4 report-q4" id="delete-q4">Delete</button>
</article>

O nome acessível se torna “Delete Q4 revenue.” Isso evita duplicar o título do relatório em um atributo.

Não rotule tudo

Nem todo elemento precisa de um rótulo ARIA.

Texto estático geralmente não precisa. Ícones decorativos não precisam. Contêineres não precisam, a menos que tenham uma função significativa de landmark ou widget. Rotular em excesso pode deixar uma página barulhenta e mais difícil de navegar.

Para imagens, use o modelo específico de imagens: imagens significativas precisam de alt útil; imagens decorativas precisam de alt="" vazio. Não use rótulos ARIA como substituto para um bom texto de imagem. Se sua equipe está misturando esses conceitos, revisite texto alt pragmático para imagens e separe alternativas de imagem de nomes de controles.

Um erro comum é dar um aria-label a todo SVG. Se o SVG está dentro de um botão e o botão já tem um nome, o ícone geralmente deve ser ocultado das tecnologias assistivas:

<button aria-label="Open menu">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Caso contrário, o usuário pode ouvir anúncios redundantes ou estranhos, dependendo da combinação de navegador e tecnologia assistiva.

Verifique o nome calculado, não apenas o código

Bugs de acessibilidade muitas vezes sobrevivem à revisão de código porque a marcação parece plausível.

Ferramentas modernas de desenvolvedor nos navegadores podem mostrar a árvore de acessibilidade calculada. No Chrome, Edge, Firefox e Safari, inspecione o elemento e procure informações de acessibilidade como função, nome e descrição. Você está verificando três coisas:

  1. A função é a que você espera?
  2. O nome acessível é claro e específico?
  3. A descrição ajuda sem substituir o nome?

Depois teste alguns fluxos com um leitor de tela real. Você não precisa se tornar especialista em tecnologia assistiva em tempo integral para perceber o básico. No macOS, o VoiceOver vem integrado. No Windows, o NVDA é amplamente usado e gratuito. Em dispositivos móveis, teste com VoiceOver no iOS e TalkBack no Android quando relevante.

Ferramentas automatizadas são úteis, mas não conseguem dizer de forma confiável se “Open”, “Read more” ou “Delete” têm contexto suficiente. Trate a automação como uma rede, não como um juiz. Isso é parecido com auditoria de performance: um relatório pode apontar áreas suspeitas, mas você ainda precisa interpretar o impacto. A mesma abordagem calma que recomendamos para ler um relatório do Lighthouse sem entrar em pânico se aplica aqui.

Uma checklist prática de revisão

Antes de publicar rótulos ARIA, pergunte:

  • Isto poderia ser HTML nativo em vez disso?
  • Há texto visível que deveria ser usado como rótulo?
  • Se existe texto visível, o nome acessível o inclui?
  • Controles repetidos são únicos quando navegados fora do contexto visual?
  • O texto de ajuda está conectado com aria-describedby, não forçado para dentro do rótulo?
  • Ícones decorativos estão ocultos das tecnologias assistivas?
  • Alguém verificou o nome de acessibilidade calculado nas ferramentas de desenvolvedor do navegador?
  • Pelo menos uma passagem com leitor de tela real foi feita no fluxo crítico?

Essa checklist captura a maioria dos problemas de rótulo antes que eles se tornem problemas para usuários.

A disciplina silenciosa de um bom ARIA

Um bom trabalho com ARIA raramente é dramático. É, em grande parte, contenção.

Use botões reais. Use rótulos reais. Mantenha nomes visíveis e acessíveis alinhados. Adicione aria-label apenas quando não houver uma fonte visível melhor. Use aria-labelledby quando a página já contém o texto certo. Use aria-describedby para instruções complementares e erros.

A plataforma web dá muito de graça aos desenvolvedores quando a usamos diretamente. ARIA existe para as lacunas. A habilidade está em saber quando há realmente uma lacuna.

Perguntas frequentes

Todo botão deve ter um aria-label?
Não. Um botão com texto visível claro geralmente já tem um bom nome acessível. Adicione `aria-label` apenas quando o texto visível estiver ausente ou for insuficiente, como em um botão somente com ícone ou em um botão “Delete” repetido que precisa de contexto.
Qual é a diferença entre aria-label e aria-labelledby?
`aria-label` fornece uma string de texto diretamente no atributo. `aria-labelledby` aponta para texto existente em outro lugar da página. Se já houver texto visível adequado, `aria-labelledby` geralmente é mais fácil de manter.
aria-label pode corrigir uma div usada como botão?
Ele pode fornecer um nome, mas não faz o elemento se comportar como um botão real. Você ainda precisaria lidar com comportamento de teclado, foco, estados e semântica esperada. Na maioria dos casos, use um `<button>` nativo.
aria-label deve corresponder exatamente ao texto visível?
Geralmente ele deve incluir o texto visível, especialmente para controles interativos. Isso apoia usuários de reconhecimento de fala e atende à intenção da orientação label-in-name da WCAG.
Como sei o que um leitor de tela vai anunciar?
Comece verificando a árvore de acessibilidade nas ferramentas de desenvolvedor do navegador para função, nome e descrição. Depois teste interações críticas com um leitor de tela real, como VoiceOver, NVDA, TalkBack ou JAWS.

Fontes e leituras adicionais

  1. WAI-ARIA Authoring Practices Guide
  2. MDN: aria-label attribute
  3. Accessible Name and Description Computation 1.2
  4. WCAG 2.2 Success Criterion 2.5.3: Label in Name
Sobre o autor
The Wux Webtools Team

Última atualização:

Continue lendo