Contraste de cores e acessibilidade: guia da WCAG

Pela WCAG 2.2, o texto de um site precisa ter razão de contraste de pelo menos 4,5:1 com o fundo (nível AA), ou 3:1 se for texto grande. Para o nível AAA, os valores sobem para 7:1 e 4,5:1. Ícones, bordas de campos e outros componentes de interface precisam de pelo menos 3:1. A razão vai de 1:1 (sem contraste) a 21:1 (preto sobre branco) e é calculada a partir da luminância relativa das duas cores.

Na prática, isso significa que um cinza #767676 é o mais claro que você pode usar em texto normal sobre fundo branco e ainda passar no AA. Este guia explica os critérios, a fórmula, os casos difíceis (texto sobre imagem, foco, placeholders) e como corrigir cores que reprovam.

Os critérios de contraste da WCAG 2.2

As Diretrizes de Acessibilidade para Conteúdo Web (WCAG) são publicadas pelo W3C. Três critérios de sucesso tratam diretamente de contraste de cor:

CritérioNívelTexto normalTexto grandeAplica-se a
1.4.3 Contraste (mínimo)AA4,5:13:1Texto e imagens de texto
1.4.6 Contraste (aprimorado)AAA7:14,5:1Texto e imagens de texto
1.4.11 Contraste não textualAA3:1Componentes de interface, estados e gráficos necessários para entender o conteúdo

O nível AA é a referência adotada pela maior parte das leis e políticas de acessibilidade. O AAA é recomendável em textos longos e em públicos com baixa visão, mas nem sempre é viável em todo o conteúdo.

O que conta como texto grande

Para a WCAG, texto grande é aquele com pelo menos 18 pontos (cerca de 24px no CSS) ou 14 pontos em negrito (cerca de 18,66px com font-weight: 700 ou mais). Um título de 20px em peso normal, portanto, ainda é “texto normal” e precisa de 4,5:1.

O que está isento

Ficam fora do 1.4.3 os logotipos e nomes de marca, o texto puramente decorativo, o texto que faz parte de uma foto sem informação relevante e os componentes de interface inativos (desabilitados).

Como a razão de contraste é calculada

O cálculo tem duas etapas: obter a luminância relativa de cada cor e comparar as duas.

1. Luminância relativa

Para cada canal R, G e B da cor em sRGB:

  1. Divida o valor de 0 a 255 por 255, obtendo um número entre 0 e 1.
  2. Linearize: se o valor for menor ou igual a 0,04045, divida por 12,92; caso contrário, calcule ((valor + 0,055) / 1,055) elevado a 2,4. (O texto da WCAG 2 cita 0,03928, herdado de uma versão antiga da norma sRGB; na prática, a diferença não altera nenhum resultado em cores de 8 bits.)
  3. Combine os canais: L = 0,2126 × R + 0,7152 × G + 0,0722 × B.

Os pesos refletem a sensibilidade do olho: o verde contribui muito mais para a luminosidade percebida do que o azul. Por isso o amarelo (#FFFF00) é tão claro e o azul puro (#0000FF) tão escuro.

2. Razão de contraste

Com L1 sendo a luminância da cor mais clara e L2 a da mais escura: razão = (L1 + 0,05) / (L2 + 0,05).

Exemplo calculado: #767676 sobre #FFFFFF

Passa no AA para texto normal. Um tom acima, #777777, já cai para cerca de 4,48:1 e reprova. Para o AAA (7:1) sobre branco, o cinza precisa ir até cerca de #595959.

Texto sobre brancoRazãoAA normalAAA normal
#9999992,85:1ReprovaReprova
#7676764,54:1PassaReprova
#5959597:1PassaPassa
Vermelho #FF00004:1Reprova (só texto grande)Reprova
Azul-marinho #00008016,01:1PassaPassa

Você não precisa fazer essa conta à mão: o verificador de contraste calcula a razão e indica os níveis atendidos.

E o APCA e a WCAG 3?

O APCA (Accessible Perceptual Contrast Algorithm) é um método alternativo que leva em conta a polaridade (texto claro sobre escuro ou o contrário), o tamanho e o peso da fonte, e expressa o resultado como um valor Lc em vez de uma razão. Ele foi estudado como candidato para a futura WCAG 3, que ainda é um rascunho de trabalho do W3C.

Isso significa que o APCA não é norma e não substitui os critérios da WCAG 2.2 em auditorias ou exigências legais. Ele pode ser útil como segunda opinião, principalmente em modo escuro, mas a conformidade continua sendo medida pela razão de contraste da WCAG 2.x.

Texto sobre imagens e gradientes

Quando o fundo é uma foto ou um gradiente, o contraste muda ponto a ponto. A regra prática é medir contra a área mais desfavorável atrás do texto: se uma parte do céu é quase branca, o texto branco precisa funcionar ali também.

Foco, hover, placeholders e desabilitados

Foco e hover

O indicador de foco é o que mostra, para quem navega pelo teclado, onde está o cursor. Ele deve ter contraste de pelo menos 3:1 com as cores ao redor (critério 1.4.11), e a WCAG 2.2 acrescentou critérios sobre o foco não ficar encoberto (2.4.11) e sobre a aparência do foco (2.4.13, nível AAA). Nunca remova o contorno com outline: none sem oferecer uma alternativa visível.

No hover, a mudança de cor também não deve reduzir o contraste do texto abaixo de 4,5:1. Um link que clareia ao passar o mouse pode ficar ilegível justamente quando a pessoa está prestes a clicar.

Placeholders

O texto de exemplo dentro de um campo é texto e, na interpretação corrente, deve atender aos 4,5:1. Os cinzas muito claros usados por padrão em muitos navegadores e bibliotecas, como #A0AEC0 (2,26:1 no branco), não passam. Além disso, placeholder não substitui o rótulo do campo: ele some quando a pessoa começa a digitar.

Componentes desabilitados

Botões e campos desabilitados estão isentos dos requisitos de contraste. Mesmo assim, tenha cuidado: se o estado desabilitado for claro demais, as pessoas podem não perceber que o botão existe ou não entender por que ele não funciona. Mostre também o motivo em texto (“preencha o e-mail para continuar”).

Bordas e ícones

A borda de um campo de formulário é o que indica onde clicar. Uma borda #E2E8F0 sobre branco tem apenas 1,23:1; um cinza como #64748B (4,76:1) atende com folga ao mínimo de 3:1.

O mesmo 3:1 vale para ícones que transmitem significado sem rótulo de texto (uma lupa para busca, uma lixeira para excluir) e para as partes de um gráfico necessárias para lê-lo, como linhas, barras e fatias. Num gráfico de linhas em tons pastel sobre branco, cada linha precisa atingir 3:1 com o fundo; se fatias ou barras vizinhas forem difíceis de distinguir, acrescente separadores, rótulos diretos ou padrões em vez de depender de diferenças sutis de cor.

Exigências legais no Brasil e no mundo

Este resumo é informativo e não constitui orientação jurídica. Para saber exatamente o que se aplica ao seu caso, consulte um profissional.

Se o seu site atende clientes de outros países, vale considerar as regras desses mercados também. Em todos os casos, seguir a WCAG 2.2 nível AA é o caminho mais seguro.

Como corrigir cores que não passam

  1. Meça o par exato de texto e fundo no verificador de contraste, anotando a razão atual.
  2. Ajuste a luminosidade, não o matiz. Escureça o texto ou clareie o fundo mantendo a mesma família de cor. Um laranja #F97316 (2,8:1 com o branco) pode virar #C2410C (5,18:1) sem deixar de parecer laranja.
  3. Troque a cor do texto. Em fundos médios, texto quase preto costuma funcionar melhor do que branco: #0F172A sobre #F97316 dá cerca de 6,4:1.
  4. Aumente o tamanho ou o peso quando for possível transformar o elemento em texto grande, que exige 3:1.
  5. Não use só a cor para transmitir informação. Erros, gráficos e links precisam de ícones, texto ou sublinhado. Teste o resultado no simulador de daltonismo.
  6. Documente os pares aprovados em tokens de design, para que a correção não se perca no próximo componente.

Resumo

Texto normal precisa de 4,5:1 (AA) ou 7:1 (AAA); texto grande, de 3:1 ou 4,5:1; componentes de interface e gráficos, de 3:1. Meça sempre os pares reais, inclusive estados de foco, hover e texto sobre imagens, e corrija ajustando a luminosidade.