# A primeira regra de ARIA aprendida da maneira difícil

> Um atributo ARIA bem-intencionado quebrou a acessibilidade de um componente que passava em todos os testes. Entenda a primeira regra de ARIA.

URL: https://dpw.dev/acessibilidade/a-primeira-regra-de-aria-aprendida-da-maneira-dificil/  
Publicado em: 2026-03-23  
Categoria: acessibilidade  
Autor: Tárcio Zemel

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.

> Artigo baseado em [I Learned The First Rule of ARIA the Hard Way](https://css-tricks.com/i-learned-the-first-rule-of-aria-the-hard-way/).

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:

[Exemplo no CodePen](https://codepen.io/anon/pen/qENBxzP)

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.

[Exemplo no CodePen](https://codepen.io/anon/pen/LEZYdwq)

Essa experiência mudou a forma de pensar sobre <a href="/acessibilidade/acessibilidade-web-para-iniciantes/">acessibilidade</a>. A maior lição foi esta: **HTML semântico faz muito mais trabalho de acessibilidade do que costumamos dar crédito** — e <a href="/miscelanea/aria-acessibilidade-web-a11y/">ARIA é simples de abusar</a> quando usada tanto como atalho quanto como suplemento.

<a href="https://www.w3.org/TR/using-aria/#secondrule" target="_blank" rel="noopener noreferrer">A primeira regra de ARIA já é bem conhecida</a>: 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

<a href="https://css-tricks.com/explaining-the-accessible-benefits-of-using-semantic-html-elements/" target="_blank" rel="noopener noreferrer">Trata-se apenas de uma página mínima com um único `<button>` nativo e sem ARIA</a>. 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.

<a href="https://css-tricks.com/buttons-vs-links/" target="_blank" rel="noopener noreferrer">Se a interação aciona uma ação, então esse elemento é um botão</a>. E neste caso, o `<button>` foi projetado para executar um script que salva alterações em um perfil de usuário:

```html
<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 `role` que 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:

```html
<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.

<figure>
  <img src="/images/blog/a-primeira-regra-de-aria-aprendida-da-maneira-dificil/devtools-role-button.webp" alt="Painel de Acessibilidade do DevTools mostrando o role acessível de button com um label de Semantic Button." />

  <figcaption>Painel de Acessibilidade do DevTools mostrando o role acessível de button com um label de Semantic Button.</figcaption>
</figure>

## 3: Adicione ARIA bem-intencionado

O problema apareceu ao tentar fazer o botão se comportar como um link:

```html
<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.

<figure>
  <img src="/images/blog/a-primeira-regra-de-aria-aprendida-da-maneira-dificil/devtools-role-link.webp" alt="Painel de Acessibilidade do DevTools mostrando o role acessível de link com um label de Semantic Button." />

  <figcaption>Painel de Acessibilidade do DevTools mostrando o role acessível de link com um label de Semantic Button.</figcaption>
</figure>

## 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:

```html
<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.

```html
<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:

1. Use HTML nativo para expressar a intenção.
2. Teste com teclado e um leitor de tela.
3. 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 <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded" target="_blank" rel="noopener noreferrer">aria-expanded</a> para comunicar estado, mostrando ARIA sendo usado para adicionar estado, não substituir semântica.

[Exemplo no CodePen](https://codepen.io/anon/pen/WbxNzob)

Esse demo usa um `<button>` nativo com `aria-expanded`, que é alternado com um pouco de JavaScript:

```js
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. <a href="/html/web-semantica-7-alternativas-div/">HTML semântico</a> 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?

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
