development
O que é ARIA? Funções, Marcos e Regiões Dinâmicas
A ARIA permite aos programadores tornar o conteúdo web dinâmico acessível aos leitores de ecrã. Saiba como funcionam as funções, os marcos e as regiões dinâmicas — e quando não os deve usar.
O que a ARIA é — e o que não é
ARIA significa Accessible Rich Internet Applications (aplicações internet ricas acessíveis). É um conjunto de atributos definido pela Web Accessibility Initiative (WAI) do W3C que permite aos programadores comunicar o significado e o estado dos elementos de interface às tecnologias de apoio, como os leitores de ecrã.
A regra mais importante sobre a ARIA é também a mais frequentemente ignorada: não utilize ARIA quando o HTML nativo consegue fazer o mesmo trabalho. Um elemento <button> já se anuncia como botão e responde a eventos de teclado. Um elemento <nav> já comunica o marco de navegação aos leitores de ecrã. Acrescentar role="button" a uma <div> e depois programar o seu comportamento é mais difícil de manter, mais fácil de partir e, normalmente, pior para a acessibilidade do que usar o elemento certo à partida.
A ARIA não:
- Torna o conteúdo visível ou interativo — apenas muda aquilo que a tecnologia de apoio anuncia
- Corrige um acesso por teclado deficiente — continua a precisar de
tabindexe de detetores de eventos - Substitui um HTML semântico bem estruturado
A ARIA ajuda genuinamente quando o HTML nativo não tem um elemento para aquilo que está a construir: um seletor de datas, um banner de notificações dinâmicas, uma caixa de combinação personalizada, uma vista em árvore. Nestes casos, a ARIA permite-lhe comunicar a semântica que o HTML não consegue exprimir.
Funções ARIA
Uma função (role) indica à tecnologia de apoio com que tipo de elemento está a lidar. Todos os elementos interativos têm uma função implícita derivada da sua etiqueta HTML. O elemento <a> tem a função link. O elemento <input type="checkbox"> tem a função checkbox. O elemento <h2> tem a função heading.
Quando constrói um elemento personalizado sem equivalente em HTML, atribui-lhe uma função explícita:
<!-- Um interruptor personalizado construído a partir de uma div -->
<div
role="switch"
aria-checked="false"
tabindex="0"
>
Modo escuro
</div>
O leitor de ecrã passa agora a anunciar isto como um controlo de interruptor e a indicar o seu estado. Sem a função, seria anunciado como texto simples e o utilizador não faria ideia de que é interativo.
Funções comuns e quando as usar
As funções de widget descrevem controlos interativos:
| Função | Usar quando |
|---|---|
button | Um elemento clicável personalizado sem etiqueta HTML melhor |
checkbox | Um interruptor personalizado de seleção múltipla |
combobox | Um campo de texto combinado com uma lista pendente |
dialog | Uma sobreposição modal (apenas quando não usa o elemento nativo <dialog>) |
listbox | Uma lista pendente personalizada |
slider | Um controlo de intervalo personalizado |
switch | Um interruptor de ligar/desligar |
tab, tablist, tabpanel | Uma interface com separadores |
tooltip | Uma descrição curta apresentada ao passar o rato ou ao receber foco |
As funções de estrutura de documento descrevem conteúdo não interativo:
article— um bloco de conteúdo autónomofigure— uma imagem com legendalist,listitem— quando é necessária semântica de lista em elementos que não são listaspresentation/none— remove a função implícita de um elemento (usar raramente e com cuidado)
Um erro crítico: acrescentar funções sem comportamento
Cada função traz consigo um contrato que os leitores de ecrã e os utilizadores de teclado esperam ver cumprido. Um role="button" tem de responder tanto a Enter como a Espaço. Um role="checkbox" tem de alternar com Espaço. Um role="link" tem de navegar com Enter.
Se acrescenta a função mas não o comportamento correspondente, está ativamente a enganar os utilizadores de tecnologia de apoio. Ouvem um controlo ser anunciado, tentam interagir com ele através do atalho de teclado esperado e não acontece nada. Isto é pior do que não ter ARIA nenhuma.
Marcos ARIA
Os marcos (landmarks) são o esqueleto de navegação da página. Permitem aos utilizadores de leitores de ecrã saltar entre as regiões principais sem terem de ler tudo o que está pelo meio — o equivalente ao olhar de um utilizador com visão a percorrer rapidamente a disposição da página.
O HTML5 introduziu elementos semânticos que correspondem diretamente a funções de marco. Use-os e os marcos vêm de graça:
| Elemento HTML | Função de marco | Finalidade |
|---|---|---|
<header> | banner | Cabeçalho de todo o site (apenas quando é o cabeçalho de nível superior, não dentro de <article>) |
<nav> | navigation | Um menu de navegação |
<main> | main | O conteúdo principal da página |
<aside> | complementary | Conteúdo secundário relacionado com o conteúdo principal |
<footer> | contentinfo | Rodapé de todo o site |
<form> | form | Um formulário (apenas quando tem um nome acessível) |
<section> | region | Uma secção nomeada (apenas quando tem um nome acessível através de aria-label ou aria-labelledby) |
Não precisa de acrescentar role="main" a um elemento <main> — é redundante. As funções de marco ARIA só são necessárias quando não pode usar o elemento HTML semântico, por exemplo numa base de código antiga que gera <div class="sidebar">:
<div class="sidebar" role="complementary" aria-label="Artigos relacionados">
<!-- conteúdo da barra lateral -->
</div>
Rotular os marcos quando tem mais do que um
Quando uma página tem várias instâncias do mesmo marco — dois elementos <nav>, dois elementos <section> com role="region" —, cada um tem de ter um nome acessível único para que os utilizadores os consigam distinguir:
<nav aria-label="Navegação principal">...</nav>
<nav aria-label="Navegação do rodapé">...</nav>
Sem rótulos, um leitor de ecrã anuncia ambos simplesmente como «navegação». Com rótulos, os utilizadores ouvem «Navegação principal, marco de navegação» e «Navegação do rodapé, marco de navegação» e podem escolher o correto a partir de uma lista de marcos.
Regiões dinâmicas ARIA
Uma região dinâmica (live region) é uma zona da página cujo conteúdo é atualizado dinamicamente e cujas atualizações devem ser anunciadas automaticamente aos utilizadores de leitores de ecrã sem que estes tenham de deslocar o foco.
O atributo central é aria-live. Aceita três valores:
off— as atualizações não são anunciadas (o valor por omissão em todos os elementos)polite— as atualizações são anunciadas depois de o utilizador terminar a tarefa em cursoassertive— as atualizações interrompem imediatamente aquilo que o leitor de ecrã está a dizer
<!-- Uma área de mensagem de estado preenchida após a submissão de um formulário -->
<div aria-live="polite" id="status-message"></div>
<script>
document.getElementById('status-message').textContent =
'A sua mensagem foi enviada.';
</script>
Quando o conteúdo de texto muda, um leitor de ecrã com aria-live="polite" espera por uma pausa na leitura e anuncia depois o novo conteúdo. Use polite para a grande maioria das atualizações dinâmicas. Reserve assertive apenas para falhas críticas — um erro de pagamento, um aviso de expiração de sessão — em que a informação é suficientemente urgente para justificar a interrupção do utilizador.
Funções de atalho para regiões dinâmicas
Há duas funções que reúnem a semântica de aria-live num único atributo:
role="status"— equivalente aaria-live="polite". Use para mensagens de sucesso, estados de carregamento e atualizações não urgentes.role="alert"— equivalente aaria-live="assertive"e implica tambémaria-atomic="true". Use para mensagens de erro e falhas críticas.
<!-- Erro anunciado imediatamente, interrompendo a leitura em curso -->
<div role="alert" id="payment-error"></div>
<!-- Atualização de estado anunciada com delicadeza após a leitura em curso -->
<div role="status" id="cart-count">3 artigos no carrinho</div>
Erros comuns com regiões dinâmicas
Acrescentar conteúdo antes de o elemento estar no DOM. O navegador regista a região dinâmica quando o elemento é analisado pela primeira vez. Se injetar o elemento e definir o seu conteúdo de texto em simultâneo, alguns leitores de ecrã perdem completamente o anúncio. Inclua sempre o contentor da região dinâmica no HTML inicial e atualize o seu conteúdo mais tarde através de JavaScript.
Usar assertive para tudo. As regiões dinâmicas assertivas interrompem o que quer que o utilizador esteja a fazer, incluindo outros anúncios. Uma contagem de resultados de pesquisa que se atualiza enquanto o utilizador escreve não justifica um role="alert". O uso excessivo de assertive produz uma experiência hostil para os utilizadores de leitores de ecrã.
Atualizar a região dinâmica com demasiada frequência. Se um indicador de progresso atualiza a sua região dinâmica a cada 100 milissegundos, a fila de leitura transborda e os utilizadores não ouvem nada de útil. Atualize o texto dinâmico apenas em marcos significativos — 25%, 50%, 75%, concluído — ou aplique um temporizador de atraso às atualizações.
Esquecer o aria-atomic. Por omissão, apenas o nó de texto alterado dentro de uma região dinâmica é anunciado. Se quiser que toda a região seja relida (e não apenas o fragmento alterado), acrescente aria-atomic="true":
<div aria-live="polite" aria-atomic="true">
<span id="count">2</span> artigos em falta
</div>
Sem aria-atomic, um leitor de ecrã pode anunciar apenas «2» quando a contagem passa de 3 para 2. Com ele, é lida a frase completa «2 artigos em falta», que é quase sempre o que se pretende.
Outros atributos ARIA essenciais
aria-label — fornece um nome acessível quando não é adequado ter texto visível:
<button aria-label="Fechar caixa de diálogo">✕</button>
aria-labelledby — aponta para outro elemento cujo texto serve de nome acessível. Preferível a aria-label quando o texto do rótulo já está visível na página:
<h2 id="billing-heading">Endereço de faturação</h2>
<form aria-labelledby="billing-heading">...</form>
aria-describedby — aponta para texto complementar que descreve um elemento para além do seu nome:
<input type="password" aria-describedby="pwd-hint">
<p id="pwd-hint">Deve ter pelo menos 12 caracteres e incluir um símbolo.</p>
aria-expanded — indica se um elemento expansível (lista pendente, acordeão, menu) está aberto ou fechado. Atualize-o em JavaScript sempre que o estado mudar:
<button aria-expanded="false" aria-controls="nav-menu">Menu</button>
<ul id="nav-menu" hidden>...</ul>
aria-hidden="true" — remove um elemento da árvore de acessibilidade. Use para ícones decorativos, texto duplicado ou elementos visuais que acrescentariam ruído para os utilizadores de leitores de ecrã:
<span aria-hidden="true">★★★★☆</span>
<span class="sr-only">4 em 5 estrelas</span>
aria-disabled="true" — marca um controlo como desativado sem o retirar da ordem de foco. Útil quando quer que os utilizadores descubram que o controlo existe e percebam por que motivo está indisponível, em vez de ser saltado silenciosamente:
<button aria-disabled="true">Submeter (preencha primeiro todos os campos)</button>
Testar ARIA na prática
Escrever atributos ARIA é simples. Acertar neles exige testes. Os analisadores automáticos detetam padrões claramente errados — um role="button" sem nome acessível, um aria-labelledby que aponta para um ID inexistente, uma região dinâmica com um valor aria-live inválido. O que não conseguem dizer-lhe é se o texto anunciado faz sentido no contexto, ou se um widget personalizado complexo se comporta corretamente quando navegado apenas com o teclado.
Para testes em condições reais, combine pelo menos dois pares de leitor de ecrã e navegador:
- NVDA + Chrome no Windows — gratuito, muito utilizado, próximo da população real de utilizadores de leitores de ecrã
- VoiceOver + Safari no macOS ou iOS — integrado, essencial para testes de acessibilidade em dispositivos móveis
- JAWS + Chrome ou Edge no Windows — pago, mas o leitor de ecrã mais utilizado em ambientes empresariais
Navegue pelos seus componentes interativos usando apenas o teclado. Ouça com atenção o que é anunciado quando abre um menu, submete um formulário com um erro de validação ou desencadeia a atualização de uma região dinâmica. Se o anúncio for ambíguo ou enganador, a implementação da ARIA está errada — independentemente do que qualquer ferramenta automática indique.
A regra que cobre tudo
A especificação da ARIA inclui cinco regras de autoria. A primeira é a mais importante:
Se puder usar um elemento ou atributo HTML nativo que já traga incorporados a semântica e o comportamento de que necessita, em vez de reaproveitar um elemento e acrescentar-lhe uma função, estado ou propriedade ARIA para o tornar acessível, então faça-o.
Construa com HTML semântico. Recorra à ARIA apenas quando o HTML se esgotar. Teste com um leitor de ecrã real. Isto cobre praticamente todas as situações com que se irá deparar.
Para uma verificação prática de como os atributos ARIA estão implementados em todo o seu site, as nossas auditorias manuais de acessibilidade incluem testes com leitores de ecrã feitos por pessoas que usam tecnologia de apoio todos os dias e conseguem detetar problemas subtis de ARIA que as ferramentas automáticas não veem.
Veja como o seu site utiliza ARIA com uma análise gratuita