ARIA (Aplicações Ricas de Internet Acessíveis) oferece às pessoas desenvolvedoras um conjunto de ferramentas poderoso para tornar interfaces web dinâmicas e complexas acessíveis a usuários de leitores de tela — mas o uso incorreto é generalizado e custoso. Este guia detalha todas as principais categorias de papéis ARIA, explica as regras de ouro do uso de ARIA e mostra exemplos de código concretos para que você possa aplicá-la corretamente.
Aqui vai um dado preocupante: de acordo com a análise do WebAIM sobre as um milhão de páginas iniciais de sites mais acessadas, páginas que incluem atributos ARIA apresentam, em média, significativamente mais erros de acessibilidade detectáveis do que páginas sem ARIA. Isso não é um argumento contra o uso de ARIA — é um argumento a favor de usá-lo corretamente. ARIA é uma das ferramentas mais poderosas no kit de acessibilidade moderno, mas também é uma das mais mal compreendidas. Use-o da forma certa e você abre seu site de maneira significativa para milhões de pessoas com deficiência. Use-o da forma errada e você piora ativamente a experiência delas.
O Que É ARIA e Por Que Ele Existe?
ARIA significa Accessible Rich Internet Applications. É um conjunto de atributos HTML, definido pela Iniciativa de Acessibilidade na Web (WAI) do W3C, que permite que desenvolvedores comuniquem informações semânticas para tecnologias assistivas como leitores de tela, linhas braille e softwares de controle por voz. Quando um navegador renderiza uma página, ele constrói duas estruturas paralelas: o DOM (o que você vê) e a Árvore de Acessibilidade (o que as tecnologias assistivas leem). Os atributos ARIA permitem modificar essa Árvore de Acessibilidade para descrever com precisão o que são componentes personalizados e como eles se comportam.
A necessidade de ARIA surgiu de um problema real. O HTML foi projetado para documentos, não para aplicações. Quando a web evoluiu para uma plataforma de experiências ricas e interativas — interfaces com abas, diálogos modais, arrastar e soltar, feeds de dados em tempo real — elementos nativos de HTML não conseguiam transmitir para um leitor de tela o que esses componentes eram ou como funcionavam. ARIA preenche essa lacuna. Como o MDN coloca, ARIA "complementa o HTML para que interações e widgets comumente usados em aplicações possam ser passados para tecnologias assistivas quando não há outro mecanismo disponível."
ARIA não altera a apresentação visual. Não adiciona comportamento. Não fornece suporte a teclado automaticamente. Ele apenas modifica o que a Árvore de Acessibilidade expõe para a tecnologia assistiva. Essa é uma distinção importante — e é a causa de muitos dos erros que desenvolvedores cometem ao recorrer ao ARIA como atalho.
A especificação é mantida pelo W3C como WAI-ARIA, atualmente na versão 1.2, com a 1.3 em desenvolvimento ativo. Ela fornece uma ontologia de papéis (roles), estados e propriedades que, em conjunto, descrevem elementos de interface de usuário acessíveis em toda a gama de padrões modernos da web.
Os Três Pilares: Roles, States e Properties
Antes de escrever uma única linha de ARIA, você precisa entender os três blocos de construção distintos que a especificação fornece. Eles não são intercambiáveis, e confundi-los é uma das fontes mais comuns de erros.
Roles definem o que um elemento é. Um role responde à pergunta: que tipo de coisa estou vendo? Exemplos incluem button, dialog, navigation, tablist e progressbar. Você aplica um role com o atributo role: <div role='button'>. O role comunica a finalidade do elemento para a tecnologia assistiva, para que a pessoa usuária saiba como interagir com ele.
States descrevem a condição dinâmica de um elemento — algo que muda conforme a pessoa interage com a página. O atributo aria-expanded informa a um leitor de tela se uma seção recolhível está aberta ou fechada. aria-checked reflete se uma checkbox personalizada está marcada. States precisam ser mantidos em sincronia com o JavaScript; um aria-expanded='false' estático que nunca muda não é apenas inútil, mas ativamente enganoso.
Properties fornecem informações descritivas, geralmente mais estáveis, sobre um elemento. aria-label dá a um elemento um nome acessível que substitui seu texto visível. aria-labelledby aponta para outro elemento cujo texto serve como rótulo. aria-describedby vincula a um texto descritivo suplementar. aria-required sinaliza que um campo de formulário precisa ser preenchido. Enquanto states tendem a mudar com frequência, properties geralmente são definidas uma vez e deixadas como estão — embora haja exceções.
Roles definem o que um elemento é. States definem como ele está se comportando neste momento. Properties fornecem contexto descritivo adicional. Você precisa dos três funcionando em conjunto para produzir um componente personalizado totalmente acessível.
A Regra de Ouro — e Por Que Ela Importa Mais do Que Você Pensa
A primeira regra do W3C para o uso de ARIA é inequívoca: se você pode usar um elemento ou atributo HTML nativo com a semântica e o comportamento de que precisa já embutidos, use-o. Não recorra ao ARIA primeiro. Isso às vezes é chamado de princípio "nenhum ARIA é melhor do que ARIA ruim" — uma frase que reflete o perigo muito real do uso bem-intencionado, porém incorreto, de ARIA.
Elementos HTML nativos carregam semântica ARIA implícita gratuitamente. Um elemento <button> já é exposto à Árvore de Acessibilidade como um botão. Ele já é focável pelo teclado. Já dispara tanto com Enter quanto com Espaço. Já anuncia seu rótulo. No momento em que você escreve <div role='button'>, você assume a responsabilidade de recriar manualmente todo esse comportamento — o tratamento de teclado, o gerenciamento de foco, a atualização de estados — em JavaScript. Isso não é uma preocupação teórica. Esquecer o suporte a teclado em um botão personalizado é um dos erros de ARIA mais comuns e mais prejudiciais em produção.
Os casos em que ARIA é genuinamente necessário tendem a se concentrar em alguns cenários: quando você está construindo um widget complexo que não tem equivalente em HTML (um carrossel, um combobox com autocomplete, uma tree view); quando você está corrigindo marcação legada em que reestruturar o DOM é proibitivamente caro; quando você está construindo um web component que precisa expor semântica personalizada; ou quando o suporte de navegador e tecnologia assistiva para um elemento nativo é tão inconsistente que o equivalente em ARIA funciona de forma mais confiável na prática.
Fora desses cenários, seu primeiro instinto deve ser sempre HTML semântico. Use <nav> em vez de <div role='navigation'>. Use <main> em vez de <div role='main'>. Use <button> em vez de <div role='button'>. Os elementos nativos são mais robustos, melhor suportados e exigem muito menos manutenção.
Um Passeio Pelas Principais Categorias de Roles ARIA
A especificação WAI-ARIA organiza roles em várias categorias. Entender essas categorias ajuda você a saber qual role usar e quando.
Landmark Roles
Landmark roles marcam as principais regiões de uma página, permitindo que pessoas que usam leitores de tela saltem diretamente para seções-chave usando atalhos de teclado. Os landmark roles mais usados são banner, navigation, main, complementary, contentinfo, search e form. Cada um deles tem um equivalente direto em HTML nativo: <header>, <nav>, <main>, <aside>, <footer> e assim por diante. Na prática, isso significa que landmark roles são quase sempre redundantes se você estiver usando HTML semântico moderno. Adicione-os apenas quando estiver preso a marcação não semântica por motivos estruturais.
<!-- Prefira isto -->
<header>
<nav>...</nav>
</header>
<main>...</main>
<footer>...</footer>
<!-- Use ARIA apenas quando você precisar usar divs -->
<div role='banner'>
<div role='navigation'>...</div>
</div>
<div role='main'>...</div>
<div role='contentinfo'>...</div>
Widget Roles
Widget roles descrevem componentes interativos que a pessoa usuária manipula diretamente. É aqui que ARIA faz seu trabalho mais importante, porque muitos padrões de widgets não têm equivalente nativo em HTML. Roles comuns de widget incluem button, checkbox, dialog, menu, menuitem, slider, tablist, tab, tabpanel, tooltip, tree e combobox.
Quando você usa um widget role, você assume total responsabilidade pela interação via teclado. O WAI-ARIA Authoring Practices Guide (APG) define padrões de teclado esperados para cada tipo de widget — por exemplo, teclas de seta para mover entre abas, Escape para fechar um diálogo, Home e End para ir ao primeiro e ao último item em uma listbox. Deixar de implementar esses padrões significa que seu componente está tecnicamente rotulado, mas é funcionalmente inutilizável para pessoas que usam apenas teclado.
<!-- Uma interface de abas personalizada -->
<div role='tablist' aria-label='Account settings'>
<button role='tab' aria-selected='true' aria-controls='panel-profile' id='tab-profile'>
Profile
</button>
<button role='tab' aria-selected='false' aria-controls='panel-security' id='tab-security' tabindex='-1'>
Security
</button>
</div>
<div role='tabpanel' id='panel-profile' aria-labelledby='tab-profile'>
<p>Profile settings content</p>
</div>
<div role='tabpanel' id='panel-security' aria-labelledby='tab-security' hidden>
<p>Security settings content</p>
</div>
Live Region Roles
Live regions são um dos recursos mais genuinamente úteis do ARIA. Elas permitem que tecnologias assistivas anunciem atualizações de conteúdo dinâmico — coisas como mensagens de status, notificações de erro, mensagens de chat e indicadores de carregamento — para pessoas que não podem ver a mudança na tela. Sem live regions, uma pessoa que usa leitor de tela ao enviar um formulário pode nunca saber se ele foi enviado com sucesso ou falhou, a menos que o foco seja movido explicitamente para o resultado.
Os principais live region roles são alert, status, log, marquee e timer. O role alert carrega uma configuração implícita de aria-live='assertive', o que significa que ele interrompe a pessoa imediatamente — apropriado para erros ou avisos urgentes. O role status usa aria-live='polite', esperando a pessoa terminar a tarefa atual antes de anunciar — ideal para mensagens de sucesso e indicadores de progresso.
<!-- Mensagem de status "polite" para feedback não urgente -->
<div role='status' aria-live='polite' aria-atomic='true'>
<!-- Injete texto dinamicamente aqui com JavaScript -->
</div>
<!-- Alerta "assertive" para erros que exigem atenção imediata -->
<div role='alert'>
Please correct the errors below before submitting.
</div>
A chave para live regions é que o contêiner deve estar presente no DOM antes de o conteúdo dinâmico ser injetado. Uma live region que é criada e populada simultaneamente é frequentemente ignorada por leitores de tela. Construa o contêiner no carregamento da página e preencha-o com JavaScript conforme os eventos ocorram.
Document Structure Roles
Document structure roles — como article, list, listitem, table, row, cell, figure e heading — descrevem a organização estrutural do conteúdo. A maioria deles agora foi substituída por elementos HTML nativos, e o MDN observa que a maior parte dos document structure roles "não deve mais ser usada, já que os navegadores agora suportam elementos HTML semânticos com o mesmo significado." A principal exceção é quando você está trabalhando com ambientes de renderização personalizados, web components ou conteúdo baseado em SVG em que elementos HTML nativos não estão disponíveis.
Propriedades ARIA Essenciais Que Todo Desenvolvedor Deve Conhecer
Além dos roles, várias propriedades ARIA aparecem constantemente em trabalhos de acessibilidade do mundo real. São estas que você usará com mais frequência:
- aria-label: Fornece um nome acessível para um elemento quando não há rótulo de texto visível disponível ou quando o texto visível é insuficiente. Casos de uso comuns: botões apenas com ícone, campos de busca sem rótulo visível e botões de fechar em modais. Observe que
aria-labelsubstitui qualquer texto visível ou rótulo nativo, então use-o com cuidado em elementos que têm texto visível. - aria-labelledby: Aponta para um ou mais elementos cujo conteúdo de texto serve como nome acessível. É mais robusto do que
aria-labelem casos complexos porque o texto do rótulo permanece sincronizado com o conteúdo visível. Aceita uma lista de IDs de elementos separados por espaço, e as tecnologias assistivas concatenam o texto referenciado na ordem. - aria-describedby: Vincula a um texto de descrição suplementar — não um nome, mas contexto adicional. Use-o para conectar campos de formulário às suas mensagens de erro ou para associar um tooltip ao elemento que ele descreve. Leitores de tela normalmente anunciam isso depois do nome e do role do elemento.
- aria-hidden: Remove um elemento inteiramente da Árvore de Acessibilidade. Inestimável para ícones decorativos, conteúdo duplicado e elementos apenas visuais que criariam ruído para pessoas que usam leitores de tela. Nunca aplique
aria-hidden='true'a um elemento focável — a pessoa ainda poderia chegar até ele com Tab, mas não receberia nenhuma informação sobre o que é. - aria-expanded: Comunica se um elemento recolhível — um dropdown, acordeão ou widget de disclosure — está atualmente aberto ou fechado. Precisa ser alternado dinamicamente com JavaScript; um valor estático é pior do que omitir o atributo completamente.
- aria-current: Indica o item atual dentro de um conjunto, mais comumente usado em navegação para marcar o link da página ativa (
aria-current='page') ou a etapa atual em um processo de múltiplas etapas.
Erros Comuns de ARIA Que Na Verdade Prejudicam a Acessibilidade
Considerando que páginas com ARIA tendem a apresentar mais erros de acessibilidade do que aquelas sem, vale a pena ser explícito sobre o que dá errado com mais frequência. Esses não são casos extremos — são padrões que aparecem em código de produção todos os dias.
Usar roles ARIA em elementos com semântica nativa forte. Alguns elementos HTML têm o que a especificação chama de "semântica nativa forte" — significados profundamente incorporados ao navegador e que não podem ser substituídos com segurança. Colocar um role inadequado em um <button> ou em um <input> pode fazer com que o navegador ignore completamente o role ARIA ou produza um comportamento contraditório que confunde tecnologias assistivas. O role que você declara precisa ser apropriado para o elemento em que é aplicado.
Esquecer o suporte a teclado com widget roles. O role='button' do ARIA informa a um leitor de tela que o elemento é um botão. Ele não torna o elemento operável via teclado. Se você usar uma <div> com role='button', você precisa adicionar tabindex='0' para torná-la focável e precisa adicionar listeners de evento para as teclas Enter e Espaço. Deixar faltar qualquer uma dessas partes quebra a experiência para pessoas que usam apenas teclado.
<!-- Incompleto e inacessível -->
<div role='button' onclick='doSomething()'>Submit</div>
<!-- Implementação correta de botão personalizado -->
<div
role='button'
tabindex='0'
onclick='doSomething()'
onkeydown='if(event.key==="Enter"||event.key===" ")doSomething()'
>Submit</div>
<!-- Ou, a resposta certa: apenas use um button -->
<button onclick='doSomething()'>Submit</button>
Usar aria-hidden em elementos focáveis. Aplicar aria-hidden='true' a um elemento focável o esconde da Árvore de Acessibilidade, mas não da navegação por teclado. Uma pessoa que usa teclado ainda pode chegar até ele com Tab, não receber nenhuma informação sobre ele e não ter como saber o que faz. Isso é uma falha da WCAG 2.1 sob o Critério de Sucesso 4.1.2 (Name, Role, Value).
States ARIA desatualizados. Deixar de atualizar aria-expanded, aria-checked, aria-selected e states semelhantes quando a interface muda deixa pessoas que usam leitores de tela com uma visão fundamentalmente incorreta da interface. Um menu que se abre visualmente, mas cujo gatilho ainda é lido como aria-expanded='false', é ativamente enganoso.
Roles redundantes. Adicionar role='navigation' a um elemento <nav>, ou role='button' a um <button>, não faz nada de útil. Isso polui o código e ocasionalmente pode confundir certas combinações de tecnologias assistivas. Confie na semântica nativa.
ARIA e WCAG: Entendendo a Conexão
ARIA não é WCAG. São especificações separadas que funcionam em conjunto. WCAG (Web Content Accessibility Guidelines) define o o quê — os resultados exigidos para conteúdo acessível. ARIA faz parte do como — um mecanismo técnico para alcançar alguns desses resultados. O critério de sucesso da WCAG mais relevante para ARIA é o 4.1.2: Name, Role, Value, que exige que todos os componentes de interface de usuário tenham um nome, exponham seu role para tecnologias assistivas e comuniquem seus estados e propriedades de forma programática. ARIA é uma das principais ferramentas para satisfazer esse critério em componentes personalizados.
ARIA também dá suporte a vários outros critérios de sucesso. Landmark roles contribuem para o 2.4.1 (Bypass Blocks) ao viabilizar a navegação por "pular para o conteúdo". Live regions costumam ser a ferramenta certa para atender ao 4.1.3 (Status Messages) na WCAG 2.1, que exige que mensagens de status sejam determináveis programaticamente sem receber foco. O uso adequado de aria-label e aria-labelledby ajuda a satisfazer 2.4.6 (Headings and Labels) e 1.3.1 (Info and Relationships).
Vale notar que a conformidade com a WCAG é cada vez mais um requisito legal. O European Accessibility Act entrou plenamente em vigor em junho de 2025, estendendo exigências obrigatórias de acessibilidade a uma ampla gama de serviços digitais do setor privado em países membros da UE. Nos Estados Unidos, o ADA continua sendo interpretado como incluindo acessibilidade na web, e exigências federais sob a Section 508 se aplicam a órgãos governamentais e organizações financiadas pelo governo federal. Entender ARIA corretamente não é apenas uma boa prática — é cada vez mais parte das suas obrigações de conformidade.
Testando Sua Implementação de ARIA
A única maneira de saber se sua implementação de ARIA realmente funciona é testá-la com tecnologias assistivas reais. Ferramentas automatizadas como axe, WAVE e Lighthouse podem detectar violações estruturais — uma propriedade obrigatória ausente, um role inválido, um aria-hidden aplicado a um elemento focável — mas não conseguem dizer se um leitor de tela anuncia seu modal de uma forma que faça sentido ou se a navegação por teclado no seu widget de árvore personalizado segue os padrões esperados.
Para testes manuais, os principais leitores de tela a cobrir são JAWS e NVDA no Windows (juntos, representam a grande maioria do uso de leitores de tela em desktop) e VoiceOver no macOS e iOS. O TalkBack cobre Android. Cada combinação de leitor de tela e navegador pode se comportar de forma diferente, então testar em pelo menos duas combinações é fortemente recomendado. Teste todos os estados interativos: abra o diálogo, expanda o acordeão, selecione a opção, dispare o alerta. Confirme que o anúncio corresponde ao que uma pessoa vidente entenderia ao olhar para a mesma interface.
Ao testar widgets personalizados, percorra o modelo de interação por teclado definido no WAI-ARIA Authoring Practices Guide para aquele tipo de widget. Se seu tablist não responde às teclas de seta, ou se seu diálogo não prende o foco, isso são falhas independentemente de quão correta a marcação ARIA pareça em uma auditoria automatizada.
Pontos-Chave
- Sempre prefira HTML semântico em vez de ARIA. Elementos nativos como
<button>,<nav>,<main>e<dialog>carregam semântica de acessibilidade embutida que é mais robusta e exige muito menos código do que seus equivalentes com ARIA em uma div. Recorra ao ARIA apenas quando o HTML nativo realmente não der conta. - Roles ARIA são uma promessa, não um atalho. Aplicar
role='button'ourole='dialog'a um elemento personalizado compromete você a implementar o modelo completo de interação por teclado para aquele tipo de widget. Roles sem comportamento correspondente criam confusão e falhas de WCAG. - Mantenha os states ARIA sincronizados com sua UI. Atributos dinâmicos como
aria-expanded,aria-checked,aria-selectede conteúdo comaria-liveprecisam ser atualizados em JavaScript conforme a interface muda. Um state desatualizado é ativamente prejudicial — ele comunica informações erradas para a pessoa usuária. - Use live regions para atualizações de conteúdo dinâmico. Qualquer conteúdo que seja atualizado sem recarregar a página — notificações, mensagens de erro, estados de carregamento, feeds de chat — precisa de uma região
aria-liveou de um role apropriado comoalertoustatuspara que pessoas que usam leitores de tela recebam automaticamente as mesmas informações que pessoas videntes veem. - Teste com tecnologias assistivas reais, não apenas com ferramentas automatizadas. Varredores automatizados detectam erros estruturais de ARIA, mas não conseguem validar se sua implementação produz uma experiência coerente e utilizável. Testes manuais com JAWS, NVDA e VoiceOver são a única forma de fechar essa lacuna.
