0% concluído

Curso de Acessibilidade para cegos

Leitores de tela, semântica, ARIA e teste — o protocolo completo para quem não enxerga.

A tese deste curso: acessibilidade não é "opcional" nem "extra". É uma regra permanente do estúdio (CLAUDE.md) e um direito. Um cego navega com leitor de tela + teclado — e o seu código precisa "falar" com ele: semântica correta, nomes acessíveis, foco visível e anúncios de mudança.

Curso interativo: há um simulador de leitor de tela, demos de foco e de aria-live, e um checklist final de auditoria (progresso salvo no navegador). Base: WCAG 2.2 AA + WAI-ARIA 1.3 (estado ago/2026).

M1

Por que acessibilidade

~20 min · motivação

~15% da população mundial vive com alguma deficiência; ~12 milhões de americanos com baixa visão dependem de leitor de tela. Acessibilidade é mercado, lei e ética.

Os números

  • 71% dos usuários com deficiência abandonam um site inacessível (Click-Away Pound).
  • ~15% de aumento médio de conversão após melhorias de acessibilidade (W3C).
  • EUA: 4.605 ações judiciais de ADA relacionadas a acessibilidade em 2024; alta de 300% entre 2018 e 2024.
  • Brasil: Lei Brasileira de Inclusão (13.146/2015) exige acessibilidade digital; e-MAG (governo federal) padroniza. Europa: European Accessibility Act em vigor.

Por que (também) é bom negócio

Site acessível é mais rápido, melhor rankeado (SEO — alt text, semântica h1-h6, HTML limpo) e mais fácil de usar por todos (quem navega no escuro, sem mouse, em telas pequenas, com leitura difícil). Acessibilidade é sinônimo de qualidade.

Os 4 princípios (POUR)

PrincípioSignificadoExemplo
PerceptívelInformação apresentada de um jeito que o usuário percebealt em imagem, transcrição em vídeo
OperávelInterface usável (teclado, sem armadilha de foco)Tudo funciona com Tab/Enter
CompreensívelTexto claro, previsívellang correto, erros anunciados
RobustoFunciona com tecnologias assistivas atuais e futurasHTML semântico, ARIA correto

Exercícios M1

  • Ex.1.1 Em 3 linhas, por que acessibilidade é decisão de produto e não "polimento"?
  • Ex.1.2 Nomeie um requisito legal brasileiro e um europeu.
  • Ex.1.3 Liste 2 exemplos de cada princípio POUR.
M2

Como um cego navega

~30 min · leitores de tela

O usuário cego não vê a tela: ouve tudo. O leitor de tela lê a árvore de acessibilidade do navegador — construída a partir do HTML/ARIA — e o usuário navega só com teclado, pulando por regiões, títulos, links e controles.

Os leitores de tela

LeitorPlataformaCuriosidade
NVDAWindowsGratuito e o mais usado; melhor com Firefox
JAWSWindowsComercial, popular em empresas/governo
VoiceOvermacOS/iOSEmbutido no Apple
TalkBackAndroidEmbutido; gestos de toque

Como navega (na prática)

  • Teclado: Tab/Shift+Tab entre controles; setas linha a linha; Enter ativa.
  • Atalhos de estrutura: NVDA+F7 lista títulos/links/landmarks; Insert+F6 lista títulos (JAWS); "roda" (rotor) no VoiceOver pula por títulos, links, landmarks.
  • Pular direto: o usuário salta para main, lista os títulos e escolhe o que quer ouvir. Por isso semântica correta é tudo.

Simulador de leitor de tela (demo)

Como o NVDA anunciaria a sua página — compare "ruim" × "semântico"

Exercícios M2

  • Ex.2.1 Liste os 4 leitores de tela e suas plataformas.
  • Ex.2.2 Por que títulos e landmarks importam tanto para um usuário de leitor?
  • Ex.2.3 Teste o simulador e escreva 1 parágrafo sobre o que mudou de um modo para o outro.
M3

Semântica e landmarks

~35 min · a base

A regra de ouro da acessibilidade: use o elemento nativo certo antes de qualquer ARIA. O HTML semântico já "fala" com o leitor de tela de graça.

O que o leitor espera

<html lang="pt-BR">                <!-- idioma para a pronúncia certa -->
<header> ... </header>              <!-- banner -->
<nav aria-label="Principal"> ... </nav>   <!-- navegação -->
<main> <h1>Título único</h1> ... </main>  <!-- conteúdo -->
<footer> ... </footer>              <!-- contentinfo -->
  • lang: sem ele, o leitor pronuncia em inglês ("João" vira "Ji-ou").
  • Landmarks: header/nav/main/aside/footer criam as "regiões" que o usuário pula entre si.
  • Títulos h1h6 em hierarquia lógica (um único h1 por página).
  • Botões de verdade (<button>), links, listas (ul/ol) — nunca div clicável com onclick.

Primeira regra do ARIA

"Não use ARIA se o elemento nativo resolver." ARIA pode quebrar o que funcionava se usado errado (ex.: aria-hidden="true" num container com conteúdo importante esconde tudo do leitor). A ordem: HTML semântico → ARIA mínima → nada.

Contraste de exemplo: botão

// ❌ div clicável — o leitor não sabe que é botão, nem foca
<div onclick="salvar()">Salvar</div>

// ✅ botão nativo — foca, ativa com Enter/Espaço, anuncia "Salvar, botão"
<button type="button" onclick="salvar()">Salvar</button>

Exercícios M3

  • Ex.3.1 Converta 3 elementos incorretos do seu projeto para HTML semântico (ex.: div clicável → button).
  • Ex.3.2 Sua página tem um único h1 e hierarquia de títulos sem pulos? Verifique.
  • Ex.3.3 Cite 1 caso onde ARIA seria realmente necessária (e 1 onde não seria).
M4

Nomes acessíveis

~35 min · o que o leitor anuncia

Todo elemento interativo precisa de um nome acessível — o texto que o leitor anuncia. Sem nome, um botão vira "botão" (e nada mais).

Como dar nome

ElementoComo nomearPrioridade
Input/select<label for>1º — placeholder NÃO é rótulo
Botão/linkTexto visível dentro1º — "Label in Name" (WCAG 2.5.3)
Ícone/svgaria-label + role="img" (ou aria-hidden se decorativo)2º — quando não há texto visível
Imagemaltalt="" se decorativa

Erros comuns (e o certo)

// ❌ placeholder como rótulo (some quando preenche; usuário perde o nome)
<input type="text" placeholder="Seu e-mail">

// ✅ label de verdade, visível e associada
<label for="email">Seu e-mail</label>
<input type="email" id="email">

// ❌ aria-label vazio — apaga o nome
<button aria-label=""><svg></svg></button>
// ✅
<button aria-label="Fechar"><svg></svg></button>

WCAG 2.5.3 "Label in Name": o nome acessível deve conter o texto visível. Nada de aria-label="Enviar formulário de contato" num botão que mostra "Enviar" — o usuário de voz (comando por fala) procura pelo que vê na tela.

Exercícios M4

  • Ex.4.1 Liste 3 formulários/controles do seu projeto sem label e corrija.
  • Ex.4.2 Encontre um ícone-só e dê aria-label descritivo (ou aria-hidden se decorativo).
  • Ex.4.3 Verifique "Label in Name": o nome acessível contém o texto visível?
M5

Teclado e foco

~30 min · operabilidade

Um usuário cego não usa mouse. Tudo precisa ser operável por teclado, com foco visível e numa ordem lógica.

Os 4 requisitos de teclado

  • Tudo operável: Tab/Shift+Tab entre controles; Enter/Espaço ativa; setas para opções.
  • Foco visível: :focus-visible { outline: 2px solid #00d4ff } — nunca outline: none sem substituto.
  • Sem armadilha de foco: em modais/accordions, o foco não pode "ficar preso"; Escape fecha e devolve o foco.
  • Skip link: link "Pular para o conteúdo" no início — o usuário não precisa Tab por 40 links de menu.
<a href="#conteudo" class="skip">Pular para o conteúdo</a>
...
<main id="conteudo"> ... </main>
/* CSS: só aparece quando recebe foco */
.skip{position:absolute;left:-9999px}
.skip:focus{left:0}

Controles customizados

Se você criar um accordion/tab/select customizado: role correto, aria-expanded, navegação por setas, tabindex gerenciado, e Enter/Espaço acionando. Prefira o elemento nativo quando existir.

Demo: ordem de foco

Ordem de tabulação — Tab navega na ordem DOM; use o teclado neste bloco
3 · Link para o topo

Ordem natural = ordem do DOM. Não use tabindex positivo (reordena de forma imprevisível); use a ordem do documento.

Exercícios M5

  • Ex.5.1 Navegue sua página só com Tab e anote onde o foco some ou fica preso.
  • Ex.5.2 Adicione um skip link se não existir.
  • Ex.5.3 Verifique se todo controle customizado responde a Enter/Espaço e setas.
M6

Conteúdo dinâmico (aria-live)

~30 min · anunciar mudanças

Se a página muda sem navegação (toast, contador, erro de formulário), o leitor de tela precisa ser avisado. É o papel das live regions.

aria-live na prática

// Área que "escuta" mudanças e anuncia quando atualiza
<div role="status" aria-live="polite">Item adicionado ao carrinho</div>

// Erro crítico — anuncia imediatamente (interrompe)
<div role="alert">E-mail inválido</div>

// O usuário não perde o lugar: polite espera a frase atual terminar.
AtributoQuandoExemplo
aria-live="polite" / role="status"Mudança útil mas não urgentecontagem de resultados, confirmação de ação
aria-live="assertive" / role="alert"Urgente, interrompeerro de formulário, perda de conexão
aria-atomic="true"Anunciar a região inteira, não só o trecho mudadocontador que muda só o número

Regra prática: atualize a área com o texto inteiro (não concatenar no JS repetidamente) e não use polite para cada micro-mudança — enche o usuário de anúncios (barulho).

Demo: live region

aria-live em ação — clique e veja o anúncio (a caixa abaixo é uma live region real)
Total: 0
Carrinho vazio

Exercícios M6

  • Ex.6.1 Encontre 2 mudanças dinâmicas no seu projeto sem aria-live e adicione.
  • Ex.6.2 Erro de formulário: ele está em role="alert"?
  • Ex.6.3 Teste a demo e anote o que o leitor anunciaria.
M7

Gráficos, imagens e cor

~30 min · conteúdo não-textual

Imagem e gráfico precisam de equivalente textual; e nenhuma informação pode depender só de cor.

Imagens

Casoalt
Imagem informativaalt="Gráfico de vendas: alta de 12% em agosto" — descreve a informação, não a estética
Decorativaalt="" (vazio) — o leitor a ignora
Botão-imagemalt = ação ("Fechar")
Gráfico SVG (como os dos nossos cursos)role="img" + aria-label explicando o que mostra, ou um resumo em texto ao lado para dados densos

Gráficos de dados: o essencial

  • Sempre dê o resumo executivo em texto ("a receita subiu 12% no trimestre") — ninguém lê eixo.
  • Para dados densos, ofereça a tabela de dados (a mesma informação em texto tabular).
  • SVG interativo: role="img" + aria-label no container, e os elementos internos aria-hidden (senão o leitor lê cada retângulo).

Cor e contraste

  • Contraste ≥ 4,5:1 para texto normal (WCAG AA); 3:1 para texto grande e UI.
  • Nunca só cor: estado de erro = cor + ícone + texto ("Erro: e-mail inválido"), não só vermelho.
  • Valide com simuladores de daltonismo (e não confie em si: ~8% dos homens têm daltonismo).

Regra de ouro para alt: "se a imagem fosse removida, o texto faria falta?" — se não, alt="". Descreva a informação, não a aparência ("foto de um homem sorrindo de terno" raramente é útil).

Exercícios M7

  • Ex.7.1 Audite as imagens do seu site: todas têm alt correto (ou alt="")?
  • Ex.7.2 Pegue um gráfico seu e escreva o resumo em texto que um leitor deve ouvir.
  • Ex.7.3 Os estados de erro do seu app dependem só de cor?
M8

Testes e ferramentas

~35 min · como comprovar

Automação pega só 30–50% dos problemas. O resto é manual: teclado + leitor de tela + bom senso.

Automatizado (rápido, não suficiente)

FerramentaO que faz
axe DevToolsExtensão; varre WCAG; acha ARIA errado, label ausente, contraste
LighthouseChrome DevTools → categorias; nota 0–100 de a11y
WAVEExtensão; marca visualmente os erros na página
pa11y / jest-axeLinha de comando / CI — falha o build com violações
# Exemplo: rodar axe-core no CI (jest-axe)
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
it('modal sem violações', async () => {
  const { container } = render(<Modal />);
  expect(await axe(container)).toHaveNoViolations();
});

Manual (o que automação não vê)

  • Só teclado: completar o fluxo inteiro (menu, formulário, modal) sem mouse.
  • NVDA + Firefox (Windows) e VoiceOver + Safari (Mac): navegar por títulos/links/landmarks e ouvir os anúncios.
  • Atalhos úteis: NVDA+F7 (lista de elementos), Insert+F6 (títulos, JAWS), rotor do VoiceOver (Ctrl+Option+U).
  • Zoom 200% e sem CSS (a ordem lógica continua correta?).

Checklist final de auditoria (WCAG 2.2 AA essencial)

Exercícios M8

  • Ex.8.1 Rode o Lighthouse (categoria Accessibility) nos seus cursos/sites e anote o score.
  • Ex.8.2 Faça um fluxo completo só com teclado e anote os problemas.
  • Ex.8.3 Ouça o seu site com o NVDA (ou VoiceOver) e descreva 1 melhoria de anúncio.
📚

Fontes e links

⚠️ WCAG/ARIA evoluem — este curso reflete WCAG 2.2 + ARIA 1.3 (ago/2026); a WCAG 3.0 está em elaboração.