Categorias
Projetos

A primeira regra de ARIA aprendida da maneira difícil

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

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

Painel de Acessibilidade do DevTools mostrando o role acessível de button com um label de Semantic Button.
Painel de Acessibilidade do DevTools mostrando o role acessível de button com um label de Semantic Button.

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.

Painel de Acessibilidade do DevTools mostrando o role acessível de link com um label de Semantic Button.
Painel de Acessibilidade do DevTools mostrando o role acessível de link com um label de Semantic Button.

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:

  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 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?