Acessibilidade HTML e ARIA
Acessibilidade não é um detalhe opcional.
Ela faz parte da qualidade real de um projeto web.
Neste post, você vai entender como o HTML contribui diretamente para acessibilidade e como usar ARIA com critério, sem substituir a semântica nativa quando ela já resolve o problema.
O que é acessibilidade na web?
Acessibilidade na web é a prática de construir páginas, sistemas e interfaces que possam ser usados pelo maior número possível de pessoas, incluindo pessoas com diferentes tipos de deficiência, limitações temporárias, contextos de uso variados e formas distintas de navegação.
Isso inclui, por exemplo, pessoas que:
- usam leitor de tela
- navegam apenas por teclado
- têm baixa visão
- têm dificuldade motora
- têm deficiência auditiva
- têm dificuldade cognitiva
- usam dispositivos móveis em ambientes difíceis
- dependem de interfaces mais claras, previsíveis e consistentes
Acessibilidade não beneficia apenas um grupo específico.
Quando uma interface é mais acessível, ela também costuma ser:
- mais clara
- mais organizada
- mais previsível
- mais fácil de usar
- mais robusta tecnicamente
Por que acessibilidade importa tanto?
A acessibilidade melhora a qualidade real do projeto em várias camadas.
Inclusão?
Mais pessoas conseguem acessar e usar o conteúdo.
Clareza?
Interfaces acessíveis costumam ser mais compreensíveis.
Navegação?
Usuários conseguem entender melhor estrutura, foco e contexto.
Robustez?
O HTML fica mais semântico e mais preparado para diferentes tecnologias assistivas.
Qualidade técnica?
Projetos acessíveis tendem a refletir melhor organização, hierarquia e boas práticas.
Qual é a relação entre HTML semântico e acessibilidade?
HTML semântico é uma das bases da acessibilidade.
Quando você usa as tags corretas, o navegador e as tecnologias assistivas entendem melhor:
- o que é um título
- o que é navegação
- o que é conteúdo principal
- o que é botão
- o que é link
- o que é formulário
- o que é tabela
- o que é mídia
- o que é conteúdo complementar
Exemplo?
<header>
<nav aria-label="Navegação principal">
<a href="/">Início</a>
<a href="/blog">Blog</a>
</nav>
</header>
<main>
<h1>Título da página</h1>
<p>Conteúdo principal.</p>
</main>
Nesse caso, a própria semântica do HTML já comunica muita informação útil.
Regra prática?
Antes de pensar em ARIA, pense em HTML correto.
O que é ARIA?
ARIA significa Accessible Rich Internet Applications.
É um conjunto de atributos usados para complementar a acessibilidade de interfaces, especialmente quando existem componentes mais dinâmicos, estados interativos ou estruturas customizadas que o HTML nativo sozinho não comunica completamente.
O que ARIA faz?
ARIA pode ajudar a informar, por exemplo:
- nome acessível
- descrição complementar
- estado expandido
- estado selecionado
- região dinâmica
- papel semântico adicional
- relação entre controle e conteúdo
Importante?
ARIA não existe para substituir HTML semântico quando o HTML nativo já resolve.
Qual é a primeira regra do ARIA?
A regra mais importante é simples:
se existe um elemento HTML nativo que já faz o trabalho, use ele.
Exemplo melhor?
<button type="button">Abrir menu</button>
Exemplo pior?
<div role="button" tabindex="0">Abrir menu</div>
Por quê?
Porque o botão nativo já oferece, por padrão:
- semântica correta
- foco
- comportamento esperado
- suporte melhor para teclado
- integração melhor com tecnologias assistivas
Regra prática?
Não use ARIA para reinventar o que o HTML já faz bem.
O que é navegação por teclado?
Navegação por teclado é a possibilidade de usar a interface sem mouse, normalmente com:
TabShift + TabEnterEspaço- setas, em alguns contextos
Esc, em alguns componentes
Por que isso importa?
Porque muitas pessoas dependem de teclado para navegar.
O que uma boa interface precisa garantir?
- foco visível
- ordem lógica de foco
- elementos interativos realmente focáveis
- comportamento previsível
- ausência de armadilhas de foco
O que é foco visível?
Foco visível é a indicação clara de qual elemento está ativo para navegação por teclado.
Exemplo de CSS conceitual?
<button type="button">Abrir painel</button>
<a href="/contato">Falar com a equipe</a>
Esses elementos precisam ter um estado visível quando recebem foco.
Por que isso importa?
Porque, sem foco visível, o usuário pode não saber onde está na interface.
Erro comum?
Remover o outline padrão sem oferecer uma alternativa acessível.
Como a hierarquia de títulos ajuda acessibilidade?
Headings ajudam tecnologias assistivas a navegar pela estrutura do conteúdo.
Exemplo?
<h1>Guia de acessibilidade</h1>
<h2>O que é HTML semântico?</h2>
<h2>O que é ARIA?</h2>
<h3>Quando usar aria-label?</h3>
Por que isso importa?
Um leitor de tela pode listar headings e permitir navegação por seções.
Boa prática?
A hierarquia deve ser lógica e consistente.
Como links acessíveis devem ser escritos?
Links devem ter texto claro e descritivo.
Exemplo ruim?
<a href="/contato">Clique aqui</a>
Exemplo melhor?
<a href="/contato">Fale com a equipe</a>
Por que isso é importante?
Porque usuários de leitor de tela muitas vezes navegam por lista de links. Se os textos forem vagos, a navegação perde sentido.
Regra prática?
O texto do link deve fazer sentido mesmo isolado.
Como botões acessíveis devem ser escritos?
Botões devem ter texto claro ou um nome acessível equivalente.
Exemplo simples?
<button type="submit">Enviar formulário</button>
Exemplo com ícone e aria-label?
<button type="button" aria-label="Fechar modal">×</button>
Quando usar aria-label?
Quando o botão não tiver texto visível suficiente para comunicar sua função.
O que é nome acessível?
Nome acessível é a forma como um elemento é identificado por tecnologias assistivas.
Esse nome pode vir de:
- texto visível
labelaria-labelaria-labelledby
Exemplo com texto visível?
<button type="button">Abrir menu</button>
O nome acessível é o próprio texto.
Exemplo com aria-label?
<button type="button" aria-label="Fechar aviso">×</button>
O nome acessível vem do atributo.
O que é aria-label?
aria-label fornece um nome acessível diretamente no elemento.
Exemplo?
<button aria-label="Fechar modal">×</button>
Quando usar?
Quando o elemento não possui texto visível suficiente.
Casos comuns?
- botões só com ícone
- controles compactos
- elementos visuais cujo significado não é claro apenas pelo conteúdo visível
Quando evitar?
Quando já existe um texto visível claro e suficiente, muitas vezes ele já resolve.
O que é aria-labelledby?
aria-labelledby usa o texto de outro elemento como nome acessível.
Exemplo?
<section aria-labelledby="titulo-beneficios">
<h2 id="titulo-beneficios">Benefícios</h2>
<p>Conteúdo da seção.</p>
</section>
Por que isso é útil?
Porque reaproveita um título visível real como nome do componente ou região.
Quando usar?
Quando já existe um heading ou rótulo visual que pode nomear a área.
O que é aria-describedby?
aria-describedby conecta um elemento a uma descrição complementar.
Exemplo?
<label for="senha">Senha</label>
<input id="senha" name="senha" type="password" aria-describedby="ajuda-senha" />
<small id="ajuda-senha">Use pelo menos 8 caracteres.</small>
O que isso faz?
A tecnologia assistiva entende que aquele campo também possui uma ajuda associada.
Quando usar?
- instruções de campo
- explicações extras
- mensagens complementares
- contexto adicional importante
O que é aria-hidden?
aria-hidden oculta um elemento das tecnologias assistivas.
Exemplo?
<span aria-hidden="true">★</span>
Quando usar?
Quando o elemento é decorativo, redundante ou não deve ser anunciado.
Cuidado?
Não use isso para esconder conteúdo importante.
Regra prática?
Se a informação é essencial, ela não deve ser escondida de leitores de tela.
O que é aria-current?
aria-current indica o item atual dentro de um conjunto.
Exemplo em menu?
<nav aria-label="Navegação principal">
<a href="/" aria-current="page">Início</a>
<a href="/blog">Blog</a>
<a href="/contato">Contato</a>
</nav>
Quando usar?
- menu principal
- breadcrumbs
- paginação
- passos de fluxo
- abas, em alguns contextos
Por que isso é útil?
Ajuda a informar qual item representa o estado atual da navegação.
O que é aria-expanded?
aria-expanded informa se um controle expansível está aberto ou fechado.
Exemplo?
<button type="button" aria-expanded="false" aria-controls="faq-1">
Ver resposta
</button>
<div id="faq-1" hidden>Resposta do item.</div>
Quando usar?
- acordeões
- dropdowns
- menus expansíveis
- painéis colapsáveis
O que o valor significa?
true: expandidofalse: recolhido
O que é aria-controls?
aria-controls indica qual elemento é controlado por aquele componente.
Exemplo?
<button type="button" aria-expanded="false" aria-controls="menu-mobile">
Abrir menu
</button>
<nav id="menu-mobile">
<a href="/sobre">Sobre</a>
</nav>
Quando usar?
Quando um controle afeta diretamente uma região específica da interface.
O que é aria-live?
aria-live define uma região cujo conteúdo atualizado deve ser anunciado automaticamente por tecnologias assistivas.
Exemplo?
<div aria-live="polite">Formulário enviado com sucesso.</div>
Quando usar?
- mensagens de sucesso
- mensagens de erro
- atualizações dinâmicas
- feedback assíncrono
- mudanças de status relevantes
Valores comuns?
politeassertive
Diferença básica?
polite: anuncia sem interromper bruscamenteassertive: maior urgência
Regra prática?
Use com moderação e apenas quando a atualização precisar ser comunicada.
O que é aria-pressed?
aria-pressed indica o estado de um botão alternável.
Exemplo?
<button type="button" aria-pressed="true">Favorito</button>
Quando usar?
- botões toggle
- favorito
- ativar/desativar recurso
- filtros ativáveis
- estados alternáveis
Importante?
Use quando o botão realmente alternar entre estados.
O que é aria-selected?
aria-selected indica item selecionado em conjuntos como abas ou listas de opções customizadas.
Exemplo?
<button role="tab" aria-selected="true">Visão geral</button>
Quando usar?
- tabs
- listas de seleção customizadas
- grids interativos
- componentes controlados por seleção
Cuidado?
Geralmente aparece em padrões mais avançados de interface, não em qualquer elemento comum.
O que é aria-disabled?
aria-disabled informa que um elemento está desabilitado do ponto de vista acessível.
Exemplo?
<div role="button" aria-disabled="true" tabindex="-1">Ação indisponível</div>
Quando usar?
Principalmente em componentes customizados.
Importante?
Para elementos nativos, muitas vezes o atributo HTML disabled já é a melhor escolha.
Exemplo melhor em elemento nativo?
<button type="button" disabled>Enviar</button>
O que é aria-modal?
aria-modal indica que uma janela ou diálogo funciona como modal.
Exemplo?
<div role="dialog" aria-modal="true" aria-labelledby="titulo-modal">
<h2 id="titulo-modal">Aviso importante</h2>
<p>Conteúdo do modal.</p>
</div>
Quando usar?
Em modais e diálogos realmente modais.
Importante?
Além do atributo, o comportamento do modal também precisa ser acessível, com:
- foco bem gerenciado
- possibilidade de fechamento
- bloqueio adequado do contexto externo, quando necessário
O que é aria-required?
aria-required informa que um campo é obrigatório.
Exemplo?
<label for="nome">Nome</label>
<input id="nome" name="nome" type="text" required aria-required="true" />
Quando usar?
Em muitos campos nativos, o próprio required já comunica a obrigatoriedade.
aria-required costuma aparecer mais em componentes customizados ou como reforço em alguns cenários.
Regra prática?
Para campos HTML nativos, normalmente required já é essencial.
O que é aria-invalid?
aria-invalid informa que o valor atual do campo é inválido.
Exemplo?
<label for="email">E-mail</label>
<input
id="email"
name="email"
type="email"
aria-invalid="true"
aria-describedby="erro-email"
/>
<small id="erro-email">Informe um e-mail válido.</small>
Quando usar?
Depois de validar e detectar erro real.
Por que isso importa?
Ajuda tecnologias assistivas a perceberem que aquele campo está com problema.
Como formulários podem ficar mais acessíveis?
Formulários são uma área crítica da acessibilidade.
Boas práticas fundamentais?
- todo campo precisa de
label - use tipos corretos de
input - use
fieldsetelegendpara agrupamentos - use instruções claras
- sinalize erro de forma compreensível
- não dependa só de cor para indicar problema
- use
aria-describedbypara ajuda adicional quando necessário - indique obrigatoriedade com clareza
Exemplo acessível?
<form action="/contato" method="post">
<fieldset>
<legend>Fale com a equipe</legend>
<label for="nome">Nome</label>
<input id="nome" name="nome" type="text" required />
<label for="email">E-mail</label>
<input id="email" name="email" type="email" required />
<label for="mensagem">Mensagem</label>
<textarea id="mensagem" name="mensagem" rows="5"></textarea>
<button type="submit">Enviar mensagem</button>
</fieldset>
</form>
Como imagens podem ficar mais acessíveis?
A principal base é o uso correto de alt.
Imagem informativa?
Use alt descritivo.
<img
src="/images/grafico.png"
alt="Gráfico de crescimento de receita entre janeiro e março"
/>
Imagem decorativa?
Use alt="".
<img src="/images/detalhe.svg" alt="" />
Por que isso importa?
Porque a imagem precisa ser interpretável mesmo sem ser vista.
Como vídeos podem ficar mais acessíveis?
Vídeos relevantes devem considerar:
- legendas
- descrição textual complementar
- controle claro de reprodução
- ausência de autoplay agressivo
- trilhas quando necessário
Exemplo com track?
<video controls poster="/images/capa-video.jpg">
<source src="/videos/aula.mp4" type="video/mp4" />
<track
src="/tracks/aula-pt.vtt"
kind="subtitles"
srclang="pt"
label="Português"
/>
</video>
Se o vídeo traz informação essencial?
Vale considerar também resumo ou transcrição textual.
Como tabelas podem ficar mais acessíveis?
Tabelas devem usar cabeçalhos e relações claras.
Exemplo?
<table>
<caption>
Comparação de planos
</caption>
<thead>
<tr>
<th scope="col">Plano</th>
<th scope="col">Preço</th>
<th scope="col">Suporte</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Básico</th>
<td>R$ 99</td>
<td>E-mail</td>
</tr>
</tbody>
</table>
Boas práticas?
- use
caption - use
th - use
scope - não use tabela para layout
O que é uma skip link?
Skip link é um link usado para pular diretamente para o conteúdo principal.
Exemplo?
<a href="#conteudo-principal" class="skip-link">
Pular para o conteúdo principal
</a>
<main id="conteudo-principal">
<h1>Título da página</h1>
</main>
Por que isso é importante?
Ajuda especialmente usuários de teclado e leitores de tela a não precisarem atravessar sempre todo o cabeçalho e menu antes de chegar ao conteúdo central.
O que é uma região nomeada com ARIA?
Algumas áreas podem se beneficiar de nomes mais claros por meio de aria-label ou aria-labelledby.
Exemplo com nav?
<nav aria-label="Navegação principal">
<a href="/">Início</a>
<a href="/blog">Blog</a>
</nav>
Exemplo com section?
<section aria-labelledby="faq-titulo">
<h2 id="faq-titulo">Perguntas frequentes</h2>
</section>
Quando isso ajuda?
Quando o nome da região torna a navegação mais clara para tecnologias assistivas.
O que é role?
O atributo role define ou complementa o papel semântico de um elemento.
Exemplo?
<div role="dialog" aria-modal="true">Conteúdo do diálogo</div>
Quando usar?
Somente quando a semântica nativa não for suficiente.
Cuidado?
Adicionar role sem necessidade pode complicar, em vez de ajudar.
Exemplo melhor, quando possível?
Se houver elemento nativo adequado, prefira ele.
Quais são alguns roles comuns?
Alguns papéis aparecem bastante em componentes customizados.
Exemplos?
dialogtabtablisttabpanelalertstatusbuttonem casos muito específicosnavigation, emboranavnativo geralmente já resolva
Regra prática?
Use roles com cautela. A prioridade continua sendo HTML semântico nativo.
Como pensar acessibilidade em componentes interativos?
Sempre pergunte:
Esse componente pode ser usado só com teclado?
O foco está visível?
O nome acessível está claro?
O estado do componente é anunciado?
O comportamento é previsível?
Existe HTML nativo que já resolveria isso melhor?
Como estruturar um accordion mais acessível?
Exemplo conceitual?
<section aria-labelledby="faq-titulo">
<h2 id="faq-titulo">Perguntas frequentes</h2>
<button type="button" aria-expanded="false" aria-controls="resposta-1">
O que é HTML semântico?
</button>
<div id="resposta-1" hidden>
HTML semântico é o uso de elementos que descrevem o papel do conteúdo.
</div>
</section>
O que esse padrão comunica?
- o botão controla uma resposta
- o estado expandido é informado
- a relação entre controle e conteúdo fica clara
Como estruturar um menu acessível?
Exemplo simples?
<header>
<a href="/" class="logo">Marca</a>
<nav aria-label="Navegação principal">
<a href="/" aria-current="page">Início</a>
<a href="/servicos">Serviços</a>
<a href="/contato">Contato</a>
</nav>
</header>
O que isso tem de bom?
- semântica nativa
- nome da navegação
- indicação da página atual
- links claros
Como estruturar mensagens dinâmicas acessíveis?
Exemplo?
<div aria-live="polite" id="mensagem-status">
Formulário enviado com sucesso.
</div>
Quando isso é útil?
Quando a mensagem aparece sem recarregar a página e precisa ser anunciada.
Cuidado?
Não use aria-live em excesso ou em áreas que mudam o tempo todo sem necessidade.
Quais são os erros mais comuns em acessibilidade?
Usar div no lugar de botão?
Isso é muito comum e geralmente piora a experiência.
Remover foco visível?
Erro sério para navegação por teclado.
Usar placeholder no lugar de label?
Campo fica mal identificado.
Escrever links vagos?
Exemplo: “clique aqui”.
Ignorar hierarquia de headings?
Dificulta navegação por estrutura.
Usar ARIA sem necessidade?
Complica e pode introduzir problemas.
Esconder conteúdo importante com aria-hidden?
Torna a informação inacessível.
Não nomear controles só com ícone?
Usuário não entende a função.
Não indicar estados dinâmicos?
Usuário não entende se algo abriu, fechou, selecionou ou falhou.
Como decidir se devo usar ARIA?
Faça perguntas simples?
O HTML nativo já resolve?
Se sim, use HTML nativo.
O componente é customizado e precisa comunicar estado?
Talvez ARIA seja necessário.
Falta nome acessível?
Talvez aria-label ou aria-labelledby.
Falta descrição complementar?
Talvez aria-describedby.
O estado muda dinamicamente?
Talvez aria-expanded, aria-live, aria-selected ou outro atributo adequado.
Existe alguma forma nativa melhor?
Se existir, prefira ela.
Subgrupo prático dos atributos ARIA mais usados
Nome acessível?
aria-labelaria-labelledby
Descrição complementar?
aria-describedby
Estado e navegação?
aria-currentaria-expandedaria-controlsaria-pressedaria-selectedaria-disabledaria-invalidaria-required
Regiões e dinâmica?
aria-livearia-modal
Visibilidade para tecnologias assistivas?
aria-hidden
Subgrupo prático de exemplos comuns
Botão com ícone?
<button type="button" aria-label="Fechar painel">×</button>
Campo com ajuda?
<label for="email">E-mail</label>
<input id="email" name="email" type="email" aria-describedby="ajuda-email" />
<small id="ajuda-email">Digite um e-mail válido.</small>
Menu com página atual?
<nav aria-label="Navegação principal">
<a href="/blog" aria-current="page">Blog</a>
</nav>
Acordeão?
<button type="button" aria-expanded="false" aria-controls="item-1">
Ver resposta
</button>
<div id="item-1" hidden>Conteúdo da resposta.</div>
Região dinâmica?
<div aria-live="polite">Alterações salvas com sucesso.</div>
Campo inválido?
<input aria-invalid="true" aria-describedby="erro-campo" />
<small id="erro-campo">Este campo precisa ser revisado.</small>
Resumo prático sobre acessibilidade e ARIA
A base da acessibilidade é?
- HTML semântico
- estrutura clara
- foco visível
- navegação por teclado
- nomes acessíveis
- estados compreensíveis
Quando pensar em ARIA?
Quando o HTML nativo não comunica tudo o que a interface precisa expressar.
Regras mais importantes?
- prefira HTML nativo
- use ARIA como complemento
- nomeie bem controles
- preserve foco visível
- pense em teclado
- torne estados e mensagens compreensíveis
- não esconda informação importante
- não use ARIA só porque “parece avançado”
Checklist rápido para revisar acessibilidade em uma página
Antes de publicar, vale conferir?
- a hierarquia de headings está lógica?
- os links têm textos claros?
- os botões têm nomes compreensíveis?
- a navegação funciona por teclado?
- o foco está visível?
- formulários têm
label? - imagens têm
altadequado? - vídeos importantes têm legenda ou contexto?
- estados dinâmicos são comunicados?
- o HTML nativo foi priorizado antes de usar ARIA?
- os atributos ARIA usados fazem sentido real?
Conclusão
Acessibilidade não é uma camada extra adicionada no fim. Ela precisa nascer junto com a estrutura da interface.
Quando você usa HTML semântico corretamente e ARIA com critério, melhora:
- inclusão
- clareza
- navegação
- previsibilidade
- robustez do projeto
- qualidade técnica geral
Dominar acessibilidade em HTML não significa decorar atributos isolados. Significa entender como pessoas diferentes usam a web e construir interfaces mais compreensíveis, mais estáveis e mais justas.
Depois desse tema, os próximos passos naturais costumam ser aprofundar em:
- atributos globais do HTML
- elementos interativos avançados
- padrões acessíveis de componentes
- estados de interface complexos
- testes práticos de acessibilidade