A primeira regra de ARIA aprendida da maneira difícil
Há algum tempo, um desenvolvedor publicou um componente que parecia acessível por todas as métricas possíveis de testar.
A navegação por teclado funcionava; roles ARIA estavam aplicados corretamente; auditorias automatizadas passavam sem uma única reclamação. E, no entanto, um usuário de leitor de tela não conseguia descobrir como acioná-lo.
Ao testar com navegação apenas por teclado e NVDA, o resultado era o mesmo: a interação simplesmente não se comportava como esperado.
Nada na checklist apontou um erro. Tecnicamente, tudo estava “certo”. Mas, na prática, o componente não era previsível.
Aqui está uma versão simplificada do componente que causou o problema:
E a correção foi muito mais fácil do que o esperado. Bastou deletar o atributo ARIA role que havia sido adicionado com as melhores intenções.
Essa experiência mudou a forma de pensar sobre acessibilidade. A maior lição foi esta: HTML semântico faz muito mais trabalho de acessibilidade do que costumamos dar crédito — e ARIA é simples de abusar quando usada tanto como atalho quanto como suplemento.
A primeira regra de ARIA já é bem conhecida: não use. Bom, use. Mas não se os benefícios e funcionalidades acessíveis necessários já estiverem embutidos — que era o caso antes de adicionar o atributo role.
O que segue é uma descrição passo a passo do que aconteceu, porque esse erro é, na verdade, uma prática bem comum. Existem muitos artigos por aí que dizem exatamente a mesma coisa, mas frequentemente ajuda internalizar ouvindo através de uma experiência real.
Nota: O artigo original foi testado usando navegação por teclado e um leitor de tela (NVDA) para observar o comportamento real de interação entre elementos nativos e modificados por ARIA.
1: Comece com a marcação mais simples possível
Trata-se apenas de uma página mínima com um único <button> nativo e sem ARIA. E, por padrão, ele permite foco via teclado e demonstra a funcionalidade de usar Tab, Enter e Space direto da caixa. Geoff recentemente defendeu esse ponto ao explicar os benefícios de acessibilidade dos elementos HTML semânticos.
Se a interação aciona uma ação, então esse elemento é um botão. E neste caso, o <button> foi projetado para executar um script que salva alterações em um perfil de usuário:
<button>Save changes</button>Essa única linha dá uma quantidade surpreendente de coisas de graça:
- Ativação por teclado com as teclas Enter e Space
- Comportamento correto de foco
- Uma
roleque a tecnologia assistiva já entende - Anúncios consistentes entre leitores de tela
Nesse ponto, não há ARIA (e isso é intencional). Mas já havia uma classe existente para estilizar botões no CSS, então ela foi adicionada:
<button class="cta">Save changes</button>2: Observe o comportamento nativo antes de adicionar qualquer coisa
Com apenas o elemento nativo no lugar, três coisas foram testadas:
- Apenas teclado (Tab, Enter, Space)
- Um leitor de tela (ouvindo como o controle é anunciado)
- Ordem de foco dentro da página
Tudo se comportou de forma previsível. O navegador estava fazendo exatamente o que os usuários esperam. Esse passo importa porque estabelece uma referência. Se algo quebrar depois, fica claro que não foi o HTML que causou.
Na verdade, é possível ver que tudo está em perfeita ordem inspecionando o elemento no painel de Acessibilidade do DevTools.

3: Adicione ARIA bem-intencionado
O problema apareceu ao tentar fazer o botão se comportar como um link:
<button class="cta" role="link">Save changes</button>A decisão foi motivada por razões de estilização e roteamento. Esse botão precisava ser estilizado um pouco diferente da classe .cta padrão, e o atributo ARIA pareceu uma opção melhor do que uma classe modificadora
Dá para perceber como a estilização começou a ditar e influenciar a funcionalidade. Um <button> ainda é o elemento correto para esse propósito, mas o desejo era que ele parecesse um link por causa dos requisitos de design.
Por que não dar a esse elemento um role de link então, certo?
Na superfície, nada parecia quebrado. Ferramentas automatizadas ficaram quietas. Mas no uso real, as rachaduras apareceram rapidamente:
- Space não ativava mais o controle de forma confiável.
- Leitores de tela anunciavam roles conflitantes.
- Usuários de teclado encontravam um comportamento que não correspondia totalmente nem a um botão nem a um link.
ARIA não adicionou clareza aqui; introduziu ambiguidade. Mas o trabalho já havia sido “testado” e nada indicava que o role do elemento havia sido misturado com outro tipo de elemento.
Novamente, basta uma rápida olhada no DevTools.

4: De volta à semântica
A correção não foi inteligente. Foi subtrativa. Os estilos foram revertidos, uma classe foi usada para estilização, e a marcação semântica anterior à mudança do role acessível foi restaurada:
<button class="cta">Save changes</button>Parece fácil: se é uma ação, use um <button>; se leva a algum lugar, use um link (<a>). Mas, na prática, decisões são tomadas a cada tecla digitada e é igualmente fácil confundir ações com destinos.
Neste caso, o elemento correto foi usado. O erro foi pensar que ARIA era um hook de estilização apropriado para CSS.
Uma vez que o elemento correto estava no lugar (sem ARIA) os problemas desapareceram. Em vez disso, bastou definir um novo nome de classe e manter estilos com estilos.
<button class="cta cta-alt">Save changes</button>Assim, simples assim, o elemento foi estilizado como necessário e o usuário que reportou o problema confirmou que tudo funcionava como esperado. Foi um erro inadvertido nascido de um mal-entendido básico sobre o lugar de ARIA na stack.
Por que isso continua acontecendo
Atributos ARIA são usados para definir a natureza de algo, mas eles não redefinem o comportamento padrão dos elementos nativos.
Quando a semântica é sobrescrita, silenciosamente assume-se a responsabilidade por:
- interações de teclado,
- gerenciamento de foco,
- anúncios esperados e
- peculiaridades específicas de plataforma.
Essa é uma grande superfície de manutenção, e é por isso que pequenas mudanças em ARIA podem ter efeitos desproporcionais e imprevisíveis.
Uma regra a seguir
Aqui está o fluxo de trabalho que mais economiza tempo e bugs:
- Use HTML nativo para expressar a intenção.
- Teste com teclado e um leitor de tela.
- Adicione ARIA apenas para comunicar estado ausente, não para redefinir roles.
Se ARIA parecer estar fazendo trabalho pesado, geralmente é um sinal de que a marcação está lutando contra o navegador.
Onde ARIA realmente pertence
Um exemplo seria um simples widget de disclosure usando um <button> nativo mais aria-expanded para comunicar estado, mostrando ARIA sendo usado para adicionar estado, não substituir semântica.
Esse demo usa um <button> nativo com aria-expanded, que é alternado com um pouco de JavaScript:
const button = document.getElementById("toggle");const panel = document.getElementById("panel");
button.addEventListener("click", () => { const expanded = button.getAttribute("aria-expanded") === "true"; button.setAttribute("aria-expanded", !expanded); panel.hidden = expanded;});O estado acessível (true/false) é comunicado corretamente sem substituir a semântica do botão.
ARIA é essencial quando:
- comunica estado expandido ou recolhido,
- anuncia atualizações dinâmicas,
- constrói widgets verdadeiramente personalizados e
- expõe relações que o HTML não consegue expressar.
Usado dessa forma, ARIA complementa o HTML semântico em vez de competir com ele.
Deixe a plataforma trabalhar por você
A maior melhoria de acessibilidade não vem de aprender mais atributos; vem de confiar naqueles que os navegadores já entendem. HTML semântico não é a linha de base que se supera. É a fundação da qual tudo mais depende.
E essa é a lição mais importante dessa experiência. Todos cometem erros. Faz parte do trabalho, infelizmente.
Mas de que servem os erros se não é possível aprender com eles, mesmo que leve uma lição difícil?