DevPath · Aprenda a programar ESPTEN

React profissional: TypeScript, SSR e acessibilidade

Acessibilidade (a11y) no React

Acessibilidade: para todos, não opcional

A acessibilidade (abreviada a11y: "a", 11 letras, "y") é construir interfaces que qualquer pessoa possa usar, incluídas as que navegam com leitor de tela, só com teclado, ou com baixa visão. Não é um extra: é qualidade de software (e, muitas vezes, um requisito legal).

A boa notícia: 90% da acessibilidade é HTML bem feito.

1) HTML semântico

Use o elemento correto para cada coisa. Um <button> já é focável, clicável com Enter/Espaço e anunciado como botão; um <div onClick> não é nada disso.

// ❌ Ruim: um div não é acessível por teclado nem se anuncia como botão
<div onClick={fechar}>Fechar</div>

// ✅ Bom
<button onClick={fechar}>Fechar</button>

O mesmo com <nav>, <main>, <header>, <ul>/<li>, cabeçalhos <h1>…<h6> em ordem: dão estrutura que as tecnologias assistivas entendem.

2) Rótulos associados aos seus campos

Todo controle de formulário precisa de um rótulo associado. A forma robusta é <label htmlFor={id}> apontando para o id do campo. No JSX se escreve htmlFor (não for, que é palavra reservada em JS), mas no DOM real se converte no atributo for.

<label htmlFor="email">E-mail</label>
<input id="email" type="email" />

Ao associá-los: o leitor de tela anuncia o rótulo ao focar o campo, e clicar no rótulo foca o input (melhor usabilidade para todos).

3) ARIA, só quando faz falta

Os atributos ARIA (aria-*) adicionam informação semântica que o HTML por si só não expressa. A primeira regra do ARIA é: não use ARIA se um elemento nativo já faz o trabalho. Mas é muito útil para nuances:

<input aria-required="true" aria-invalid={temErro} />
<button aria-label="Fechar diálogo">✕</button>     {/* botão só com um ícone */}
<nav aria-label="Principal">…</nav>

4) Foco e navegação por teclado

Muita gente navega sem mouse. Garanta que:

5) IDs únicos com useId

Associar label e input por id tem um problema no React: se o componente é usado várias vezes na página, um id fixo ("email") se duplicaria, e os ids devem ser únicos. A solução é o hook useId, que gera um identificador único e estável (além disso funciona bem com SSR/hidratação):

function Campo({ rotulo }) {
  const id = React.useId();
  return (
    <p>
      <label htmlFor={id}>{rotulo}</label>
      <input id={id} />
    </p>
  );
}

Importante: useId é para ids de acessibilidade (vincular elementos), não para keys de listas. Reutilize o mesmo id (com sufixos se precisar de vários: ${id}-error) para relacionar elementos do mesmo componente.

Nos exercícios deste runtime, use React.useId() (com o prefixo React.) para gerar o id.

Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← Renderização no servidor: CSR, SSR, SSG e Server ComponentsVer o módulo →