Funções e atributos ARIA: melhores escolhas comparadas
As funções e atributos ARIA da especificação WAI-ARIA 1.2 do W3C superam a centena, embora um punhado resolva a maioria dos problemas de acessibilidade em widgets XHTML e CSS. Uma função define o que é um elemento e um atributo de seu estado ou relacionamento, mas ARIA não modifica o comportamento do navegador: cada papel adicionado exige implementar interação com JavaScript.
Accessible Rich Internet Applications (ARIA) é uma especificação W3C que adiciona semântica a elementos HTML que não os possuem em formato nativo. Um papel descreve o que é um elemento (um botão, uma tab, um diálogo), enquanto um atributo descreve seu estado ou seus relacionamentos (aria-expanded, aria-controls, aria-labelledby). A primeira regra do ARIA, publicada pelo W3C em Using ARIA, é contundente: se existe um elemento HTML nativo que já faz o trabalho, use-o e não adicione ARIA.
A razão é que o ARIA não modifica o comportamento do navegador. Um <div role="button"> não recebe foco com Tab, não responde à tecla Enter ou espaço e não é enviado com um formulário. Só muda o que a tecnologia assistiva anuncia. Toda interação deve ser implementada com JavaScript e gerenciada cuidadosamente. Em projetos XHTML/CSS onde o HTML é estático e o JS é mínimo, isso significa que cada uma das funções e atributos da ária adicionados é uma promessa que seu código deve cumprir.
A segunda regra do ARIA pede para não alterar a semântica nativa, a menos que seja imprescindível. Um <h2 role="tab"> quebra a estrutura dos títulos e confunde os leitores de tela que navegam por regiões. A terceira regra exige que todos os controles ARIA possam ser operados com um teclado. A quarta pede para não usar aria-hidden="true" em elementos que recebem foco. A quinta, e mais esquecida, nos lembra que qualquer elemento interativo requer um nome acessível: uma função sem rótulo é um botão mudo.
Como escolher: critérios antes da lista
Escolher uma função ou atributo não é uma questão de gosto. Esses critérios, aplicados em ordem, evitam a maioria dos erros relacionados às funções e atributos da ária:
- Existe um elemento HTML nativo? Se sim, use-o.
<button>,<details>,<dialog>,<input type="checkbox">cobrem mais casos do que as pessoas pensam. - O widget precisa de estados dinâmicos? Se ele mudar entre aberto/fechado, selecionado/não selecionado ou expandido/recolhido, você precisará de atributos de estado (
aria-expanded,aria-selected,aria-pressed). - Precisa de relacionamentos entre elementos? Atributos de relacionamento (
aria-controls,aria-labelledby,aria-describedby,aria-owns) conectam peças que a árvore de acessibilidade não pode inferir do DOM. - Precisa de anúncios ao vivo? Regiões ativas (
aria-live,role="status",role="alert") resolvem atualizações sem mover o foco. - Posso mantê-lo? Um padrão ARIA complexo sem testes de teclado ou leitor de tela é pior do que não ter nada.
O custo de manutenção é o critério mais ignorado. Um role="tablist" requer gerenciamento de teclas de seta, rotação de tabindex, sincronização de aria-selected e aria-controls e ocultação correta de painéis inativos. Caso a equipe não consiga dar conta disso, um conjunto de links com âncoras fica mais acessível e barato.
Relacionado: — com plano gratuito para começar hoje mesmo.
Comparativo dos papéis ARIA mais úteis
A tabela seguinte resume as funções que aparecem repetidamente em auditorias reais, com seu equivalente nativo quando existe e a armadilha mais comum.
| Função | Para que serve | Alternativa nativa | Armadilha frequente |
|---|---|---|---|
botão | Controle que executa uma ação | <botão> | Não adicionar manipulação de Enter/Espaço nem tabindex="0" |
link | Navegação para outro URL | <ahref> | Usar para ações que não navegam |
diálogo | Janela modal ou não modal | <caixa de diálogo> | Não capturar o foco nem devolvê-lo ao fechar |
tablist / tab / tabpanel | Interface de abas | Nada direto | Não sincronizar aria-selected com o painel visível |
menu / menuitem | Menu de aplicação | <select> ou lista de links | Usá-lo para menus de navegação web |
alert | Mensagem urgente e imediata | role="status" para não urgente | Abusar dele e saturar o leitor de tela |
status | Atualização informativa | <saída> | Não inseri-lo no DOM antes de atualizar |
progressbar | Progresso de uma tarefa | <progresso> | Não atualizar aria-valuenow |
tooltip | Descrição emergente | título (limitado) | Não associe-o com aria-describedby |
combobox | Campo com lista de sugestões | <datalist> (limitado) | Não anuncia o número de resultados |
A escolha entre role="alert" e role="status" é um bom exemplo de decisão com nuances em relação aos papéis e atributos da ária. alert interrompe a leitura atual do leitor de tela; status espera o usuário terminar. Para um erro de validação de formulário, alert é apropriado. Para “3 resultados encontrados” enquanto o usuário escreve, status está correto e alert resulta em ser intrusivo.
Atributos ARIA imprescindíveis e como se combinam
Os atributos estão associados a quatro famílias, e cada uma resolve um problema distinto.
Vale a pena dar uma olhada: — Acessibilidade gerenciada: automatização combinada com revisão humana.
Etiquetado. aria-label fornece um nome quando não há texto visível. aria-labelledby faz referência ao id de outro elemento e é preferível quando o texto já existe na tela, pois mantém uma única fonte de verdade. aria-describedby adiciona uma descrição mais longa, como o texto de ajuda de um campo. A diferença importa: o nome é o que o usuário ouve ao focar; a descrição é um contexto adicional que pode ser interrompido.
Estados. aria-expanded (true/false) para acordeões e menus suspensos. aria-selected para guias e opções. aria-checked para caixas de seleção personalizadas, com o valor mixed para estados de três estados. aria-pressed para botões de alternância. aria-disabled quando o elemento ainda pode ser focado, mas não operável, ao contrário do atributo nativo disabled, que o remove da ordem de tabulação.
Relações. aria-controls indica qual elemento um botão controla. aria-owns reorganiza a árvore de acessibilidade quando o DOM não reflete o relacionamento visual. aria-activedescendant permite manter o foco em um contêiner enquanto anuncia o elemento ativo, um padrão comum em comboboxes.
Regiões ativas. aria-live="polite" ou "assertivo" definem urgência. aria-atomic="true" faz com que todo o bloco seja anunciado em vez de apenas a parte modificada. aria-relevant filtra quais alterações são anunciadas.
Um detalhe que muitas vezes é esquecido: os atributos ARIA só funcionam em elementos com uma função válida. aria-expanded em um <div> sem um papel não será anunciado. E os valores booleanos ARIA são strings de texto ("true", "false"), não valores booleanos JavaScript; escrever aria-expanded="false" como uma propriedade booleana produzirá resultados inconsistentes.
Erros que prejudicam a acessibilidade de um widget
O erro mais caro é usar ARIA para organizar um HTML mal estruturado. Adicionar role="navigation" a um <div> quando já existe um <nav> disponível duplica as regiões e confunde a navegação por marcos (landmarks).
Relacionado: — A que acredita sua experiência e acessibilidade.
O segundo erro é o foco. Um widget modal que não move o foco quando aberto, não o prende enquanto está aberto e não o retorna ao gatilho ao fechar, deixa o usuário do teclado navegando por um conteúdo invisível. O elemento nativo <dialog> resolve parte disso, mas não tudo: retornar o foco ainda é responsabilidade do desenvolvedor.
O terceiro erro é ocultar elementos aria-hidden que continuam sendo enfocaveis. Um menu fechado com aria-hidden="true" mas sem display: none ou visibility: hidden mantém seus links na ordem de tabulação, e o usuário enfoca elementos que não podem ser vistos. A combinação correta é ocultar visualmente e a árvore de acessibilidade ao mesmo tempo.
O quarto erro é o nome acessível ausente. Um <button> com um único ícone SVG requer um aria-label ou um <span class="visually-hidden"> com texto. Um SVG decorativo requer aria-hidden="true" e focusable="false" portanto, o Internet Explorer e alguns navegadores mais antigos não o incluem na ordem de tabulação.
Ferramentas para testar funções e atributos ARIA
Não existe nenhuma ferramenta para testar com um leitor de tela real, mas a combinação de várias ferramentas detecta a maioria das falhas nas funções e atributos da ária.
Validação estática. O validador W3C ARIA (parte do Nu HTML Checker) detecta funções inexistentes, atributos mal escritos e combinações proibidas. ax DevTools e Lighthouse apontam funções sem nomes acessíveis e atributos obrigatórios ausentes.
Inspeção da árvore de acessibilidade. Os DevTools do Chrome e do Firefox permitem que você veja a árvore de acessibilidade exatamente como ela é recebida pela tecnologia assistiva. É a maneira mais rápida de verificar se uma função foi realmente aplicada e qual nome acessível o navegador calculou.
Teste manual. Navegue por todo o widget apenas com o teclado (Tab, Shift+Tab, setas, Enter, Espaço, Escape) e depois com NVDA no Windows, JAWS se disponível, ou VoiceOver no macOS e iOS. A combinação de um leitor de desktop e um leitor móvel cobre a maioria dos casos reais.
Documentação de referência. O ARIA Authoring Practices Guide (APG) do W3C inclui padrões abrangentes com teclado e exemplos de código. Esta é a fonte que deve ser consultada antes de inventar um novo padrão.
Como decidir em um projeto XHTML/CSS real
Em sites XHTML com CSS e JavaScript leves, a estratégia mais econômica é começar com HTML nativo e adicionar ARIA apenas onde o nativo não chega. Um formulário com <label>, <fieldset> e <legend> corretos requer muito pouco ARIA. Uma tabela de dados com <th scope> também não. As funções ARIA surgem quando aparecem padrões que o HTML não cobre: guias, acordeões, caixas de combinação com filtragem, caixas de diálogo modais e notificações dinâmicas.
É aconselhável documentar cada uso de funções e atributos ARIA no próprio código com um comentário explicando por que ele está lá. Quando alguém refatorar o componente seis meses depois, saberá se o aria-controls ainda é necessário ou se ficou órfão. Atributos ARIA órfãos — que apontam para ids que não existem mais — são uma fonte silenciosa de falhas que nenhum validador detecta de forma confiável.
Por fim, trate a acessibilidade como parte da definição de “pronto” do componente, e não como uma auditoria subsequente. Um widget com funções ARIA testado com teclado e leitor de tela desde o primeiro commit custa muito menos do que um reparado após a auditoria.
Principais conclusões
- Papéis e atributos ARIA não adicionam comportamento: um papel sem teclado e gerenciamento de foco é pior do que não ter nada.
- A primeira regra do ARIA é usar HTML nativo sempre que existir;
<button>,<dialog>e<details>cobrem mais casos do que se imagina. - Os atributos são agrupados em rotulagem, estados, relacionamentos e regiões ativas; cada família resolve um problema diferente.
role="alert"interrompe erole="status"espera: a escolha incorreta satura o usuário do leitor de tela.- Os valores booleanos ARIA são strings (
"true"/"false"), e os atributos só funcionam em elementos com uma função válida. - É obrigatório testar com teclado e leitor de tela real; os validadores detectam apenas uma parte das falhas.
Fontes e leituras adicionais
- WAI-ARIA — Wikipedia: Web Accessibility Initiative – Accessible Rich Internet Applications (WAI-ARIA) é uma especificação técnica publicada pelo World Wide Web Consortium (W3C) que…
Perguntas frequentes
Qual é a diferença entre um papel e um atributo ARIA?
Uma função define o que é um elemento para tecnologia assistiva, como role="tab" ou role="dialog". Um atributo descreve seu estado ou seus relacionamentos, como aria-expanded ou aria-labelledby. As funções são aplicadas ao elemento que representa o componente; atributos geralmente são aplicados ao mesmo elemento ou àqueles que estão relacionados a ele.
Por que devo usar ARIA em vez de HTML nativo?
Somente quando não há nenhum elemento HTML que cubra o padrão. A primeira regra do W3C ARIA é explícita: se houver um elemento nativo, use-o. As funções ARIA são necessárias para guias, acordeões, caixas de combinação com filtragem e caixas de diálogo modais, entre outros padrões que o HTML não pode implementar sozinho.
O que significa que um elemento tem um nome acessível?
Um nome acessível é o texto que o leitor de tela anuncia ao focar o elemento. É calculado a partir do conteúdo, de aria-label, de aria-labelledby ou de um <label> associado, em uma ordem de prioridade definida pela especificação. Uma função interativa sem um nome acessível é um controle que o usuário não consegue identificar.
Por que meu role="button" não responde ao teclado?
Porque ARIA não adiciona comportamento. Um <div role="button"> precisa de tabindex="0" para receber foco e manipuladores keydown para Enter e Space. A solução mais simples e robusta é utilizar o elemento nativo <button>, que já inclui foco, ativação do teclado e envio de formulário.
É ruim usar aria-hidden="true"?
É correto ocultar conteúdos decorativos ou duplicados da árvore de acessibilidade, mas nunca deve ser aplicado em elementos que recebem foco. Se um elemento focável for deixado com aria-hidden="true", o usuário do teclado pode focar em algo que o leitor de tela não anuncia. Sempre combine-o com uma ocultação visual real.
Quais ferramentas validam as funções e atributos ARIA?
O W3C Nu HTML Checker inclui validação de funções e atributos ARIA e detecta funções inexistentes ou combinações proibidas. axe DevTools e Lighthouse apontam funções sem nome acessível e atributos obrigatórios ausentes. Para verificar o resultado final, o inspetor de árvore de acessibilidade do navegador DevTools mostra exatamente o que a tecnologia assistiva recebe.
Perguntas frequentes
Qual é a diferença entre um papel e um atributo ARIA?
Uma função define o que é um elemento para tecnologia assistiva, como role='tab' ou role='dialog'. Um atributo descreve seu estado ou seus relacionamentos, como aria-expanded ou aria-labelledby. As funções são aplicadas ao elemento que representa o componente; atributos geralmente são aplicados ao mesmo elemento ou àqueles que estão relacionados a ele.
Por que devo usar ARIA em vez de HTML nativo?
Somente quando não há nenhum elemento HTML que cubra o padrão. A primeira regra do W3C ARIA é explícita: se houver um elemento nativo, use-o. As funções ARIA são necessárias para guias, acordeões, caixas de combinação com filtragem e caixas de diálogo modais, entre outros padrões que o HTML não pode implementar sozinho.
O que significa que um elemento tem um nome acessível?
Um nome acessível é o texto que o leitor de tela anuncia ao focar o elemento. É calculado a partir do conteúdo, de aria-label, de aria-labelledby ou de um <label> associado, em uma ordem de prioridade definida pela especificação. Uma função interativa sem um nome acessível é um controle que o usuário não consegue identificar.
Por que meu `role='button'` não responde ao teclado?
Porque ARIA não adiciona comportamento. Um <div role='button'> precisa de tabindex='0' para receber manipuladores de foco e keydown para Enter e Space. A solução mais simples e robusta é utilizar o elemento nativo <button>, que já inclui foco, ativação do teclado e envio de formulário.
É errado usar `aria-hidden='true'`?
É correto ocultar conteúdos decorativos ou duplicados da árvore de acessibilidade, mas nunca deve ser aplicado em elementos que recebem foco. Se um elemento focável for deixado com aria-hidden='true', o usuário do teclado poderá focar em algo que o leitor de tela não anuncia. Sempre combine-o com uma ocultação visual real.
Quais ferramentas validam as funções e atributos ARIA?
O W3C Nu HTML Checker inclui validação de funções e atributos ARIA e detecta funções inexistentes ou combinações proibidas. ax DevTools e Lighthouse apontam funções sem nome acessível e atributos obrigatórios ausentes. Para verificar o resultado final, o inspetor de árvore de acessibilidade do navegador DevTools mostra exatamente o que a tecnologia assistiva recebe.
Cumprir WCAG sem tocar no código?
Superposição de IA que promete cumprimento WCAG em 48 horas