Texto cinza-claro sobre fundo branco fica elegante no monitor do designer e ilegível para quem tem baixa visão, para quem usa o celular sob o sol ou para qualquer pessoa depois dos quarenta anos. As Diretrizes de Acessibilidade para Conteúdo Web (WCAG) resolvem isso com um número: a razão de contraste. Este guia explica como ela é calculada, quais valores mínimos a WCAG exige e mostra um exemplo completo.
O que a razão de contraste mede
A razão de contraste compara a luminosidade de duas cores, a do texto e a do fundo. Ela vai de 1:1 (cores idênticas, nenhum contraste) até 21:1 (preto sobre branco, o máximo possível). Quanto maior, mais fácil de ler.
Os mínimos exigidos
- Nível AA, texto normal: pelo menos 4,5:1 (critério de sucesso 1.4.3).
- Nível AA, texto grande: pelo menos 3:1. Considera-se grande o texto a partir de 18 pontos (cerca de 24 px), ou 14 pontos (cerca de 18,7 px) se estiver em negrito.
- Nível AAA: 7:1 para texto normal e 4,5:1 para texto grande (critério 1.4.6).
- Componentes de interface e gráficos: pelo menos 3:1 contra as cores vizinhas, como a borda de um campo de formulário ou um ícone essencial (critério 1.4.11, da WCAG 2.1).
Na prática, o nível AA é o alvo mais comum e o exigido em boa parte das regulamentações de acessibilidade digital.
Como a razão é calculada
O cálculo tem três etapas.
1. Converter cada canal de cor
Cada canal (vermelho, verde e azul), que vai de 0 a 255, é dividido por
255 e passa por uma correção para refletir como o olho percebe a
luminosidade (a conversão a partir do espaço sRGB). Chamando o valor
normalizado de c:
se c ≤ 0,03928: canal = c / 12,92
senão: canal = ((c + 0,055) / 1,055) ^ 2,4
2. Calcular a luminância relativa
O olho é mais sensível ao verde do que ao vermelho e ao azul, e a fórmula reflete isso com pesos diferentes:
L = 0,2126 × R + 0,7152 × G + 0,0722 × B
O resultado vai de 0 (preto absoluto) a 1 (branco absoluto).
3. Comparar as duas luminâncias
razão = (L_mais_clara + 0,05) / (L_mais_escura + 0,05)
O 0,05 representa a luz ambiente e evita divisão por zero no preto.
Exemplo: cinza #767676 sobre branco
Como o cinza tem os três canais iguais (0x76, ou 118), basta
calcular um deles:
118 / 255 = 0,4627
canal = ((0,4627 + 0,055) / 1,055) ^ 2,4 ≈ 0,1812
L(cinza) = 0,1812 (os pesos somam 1, então L = canal)
L(branco) = 1,0
razão = (1,0 + 0,05) / (0,1812 + 0,05) = 1,05 / 0,2312 ≈ 4,54
Resultado: 4,54:1, que passa por pouco no nível AA para
texto normal. Já o cinza #777777, quase idêntico a olho nu,
dá 4,48:1 e reprova. Essa é a razão pela qual
calcular vale mais que "achar que dá para ler". Para outros valores de
referência: #595959 sobre branco dá 7,00:1 (AAA),
e vermelho puro #FF0000 sobre branco dá apenas 4,00:1, o que
reprova para texto normal.
Você não precisa fazer essas contas à mão: o verificador de contraste WCAG calcula a razão para qualquer par de cores, e o color picker mostra os valores em HEX, RGB e HSL.
Erros comuns
- Texto sobre imagem ou gradiente: o contraste precisa valer na pior região por trás do texto. Um degradê que começa escuro e termina claro pode reprovar em uma das pontas. Ao montar degradês, o gerador de gradiente CSS ajuda a visualizar as cores.
- Placeholders e textos de ajuda: também são texto e precisam atender ao mínimo, ainda que o design queira que "pareçam apagados".
- Estados de foco, hover e desabilitado: o indicador de foco de teclado precisa ser visível (3:1 como componente). Componentes inativos e logotipos são as exceções previstas.
- Depender só da cor: contraste alto não resolve o caso de informação transmitida apenas pela cor (como "campos com erro em vermelho"). Acrescente ícone, texto ou padrão.