Erros Comuns & Checklist
Os erros mais frequentes com exemplos de código · Checklist WCAG 2.2 AA
Erros Comuns e Como Corrigi-los
Imagens sem texto alternativo ou com alt genérico
Errado
<img src="grafico.png">
<img src="foto.jpg" alt="imagem">
<img src="logo.png" alt="logo">
<img src="icone.svg" alt="icon">
Correto
<!-- Informativa: descreva o conteúdo -->
<img src="grafico.png"
alt="Vendas por região: Sul 45%, Sudeste 38%">
<!-- Logo: nome da empresa -->
<img src="logo.png" alt="Empresa XYZ">
<!-- Decorativa: alt vazio -->
<img src="divisor.png" alt=""
role="presentation">
Foco visível removido com outline:none
Errado
/* Oculta o foco para TODOS */
* { outline: none; }
button:focus { outline: 0; }
a:focus { outline: none; }
Correto
/* Remove apenas para mouse,
mantém para teclado */
:focus:not(:focus-visible) {
outline: none;
}
:focus-visible {
outline: 3px solid #facc15;
outline-offset: 3px;
}
Janelas modais sem gestão de foco
Quando um modal abre: foco vai para o primeiro elemento focável dentro dele. Quando fecha: foco retorna ao elemento que o abriu. O foco deve ficar preso dentro do modal (focus trap).
<div role="dialog"
aria-modal="true"
aria-labelledby="modal-titulo"
aria-describedby="modal-desc">
<h2 id="modal-titulo">Confirmar exclusão</h2>
<p id="modal-desc">
Esta ação não pode ser desfeita.
</p>
<button>Confirmar</button>
<button>Cancelar</button>
</div>
Tabelas sem cabeçalhos semânticos
Errado
<table>
<tr>
<td>Nome</td>
<td>Idade</td>
</tr>
<tr>
<td>Ana</td>
<td>30</td>
</tr>
</table>
Correto
<table>
<caption>Lista de colaboradores</caption>
<thead>
<tr>
<th scope="col">Nome</th>
<th scope="col">Idade</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ana</td><td>30</td>
</tr>
</tbody>
</table>
Mensagens de erro sem associação ao campo
Errado
<input type="email" />
<span style="color:red">
E-mail inválido
</span>
<!-- leitor de tela não sabe
a qual campo pertence o erro -->
Correto
<label for="email">E-mail</label>
<input type="email" id="email"
aria-invalid="true"
aria-describedby="email-erro" />
<span id="email-erro" role="alert">
Insira um e-mail válido:
usuario@site.com
</span>
Conteúdo que aparece apenas no hover
Tooltips e menus que aparecem apenas no hover são inacessíveis para usuários de teclado e toque. O critério WCAG 1.4.13 (AA) exige que conteúdo que aparece no hover também:
- Possa ser descartado sem mover o ponteiro ou foco (Esc)
- Permaneça visível quando o ponteiro se move sobre ele
- Persista até ser descartado pelo usuário ou não ser mais relevante
Use :hover + :focus-visible juntos, e implemente o Esc para fechar via JavaScript.
iframes sem título
Errado
<iframe src="mapa.html">
</iframe>
<iframe src="video-embed">
</iframe>
Correto
<iframe
src="mapa.html"
title="Mapa de localização da loja">
</iframe>
<iframe
src="video-embed"
title="Vídeo: Como usar o produto">
</iframe>
Linguagem da página não declarada
Errado — sem lang
<html>
...
</html>
<!-- Leitor de tela usa idioma
padrão do sistema, podendo
pronunciar PT com sotaque EN -->
Correto
<html lang="pt-br">
<!-- Trecho em outro idioma: -->
<p>
O conceito de
<span lang="en">
responsive design
</span>
é fundamental.
</p>
Checklist WCAG 2.2 — Nível AA
Use como ponto de partida para auditar seu projeto. Lembre-se: ferramentas automáticas cobrem apenas ~35% dos problemas — o restante exige teste manual.
Estrutura e Semântica
- ☐ Idioma declarado:
<html lang="pt-br"> - ☐ Um único
<h1>, hierarquia de cabeçalhos correta - ☐ Landmarks HTML5 usados corretamente
- ☐ Skip link como primeiro elemento focável
- ☐
<title>descritivo e único por página - ☐ Múltiplas navegações com
aria-labeldistintos - ☐
aria-current="page"no link ativo da navegação
Formulários
- ☐ Todos os campos com
<label>visível associado - ☐ Campos obrigatórios: indicador visual +
aria-required - ☐ Erros descritivos vinculados com
aria-describedby - ☐
autocompleteconfigurado para dados pessoais - ☐ Grupos com
<fieldset>e<legend> - ☐ Erros identificados por texto, não só por cor
- ☐ Sem CAPTCHA inacessível sem alternativa
Imagens e Mídia
- ☐ Imagens informativas com
altsignificativo - ☐ Imagens decorativas com
alt="" - ☐ Vídeos com legendas sincronizadas
- ☐ Áudios com transcrição
- ☐ Vídeos informativos com audiodescrição
- ☐ Sem áudio automático sem controle
- ☐
<iframe>com atributotitle
Teclado e Foco
- ☐ Toda funcionalidade acessível por teclado
- ☐ Foco visível com contraste ≥ 3:1
- ☐ Sem armadilha de foco não intencional
- ☐ Ordem de tabulação lógica
- ☐ Modais com focus trap e retorno de foco
- ☐ Menus dropdown operáveis por teclado
- ☐ Esc fecha modais, tooltips e popups
Cores e Visual
- ☐ Contraste de texto ≥ 4,5:1 (normal) / 3:1 (grande)
- ☐ Contraste de componentes UI ≥ 3:1
- ☐ Informação não transmitida apenas por cor
- ☐ Funciona com modo alto contraste do OS
- ☐ Zoom 200% sem perda de conteúdo
- ☐ Sem rolagem horizontal em 320px (zoom 400%)
- ☐ Sem conteúdo que pisca >3 vezes/segundo
Conteúdo Dinâmico
- ☐ Mudanças de status anunciadas via
aria-live - ☐ Carrosséis com controles de pausa/anterior/próximo
- ☐ Animações desativáveis (
prefers-reduced-motion) - ☐ Timeouts avisam o usuário e permitem extensão
- ☐ Conteúdo novo não move o foco inesperadamente
- ☐ SPA atualiza o
<title>na mudança de rota - ☐ Status de carregamento anunciado