Por que contraste é um número, não uma opinião
Legibilidade não é questão de gosto. Um texto que você lê sem esforço na penumbra do escritório pode desaparecer para uma pessoa com baixa visão, para alguém com catarata, para o mesmo usuário sob luz solar direta ou num celular com brilho reduzido para poupar bateria. Por isso a WCAG (Web Content Accessibility Guidelines, do W3C) não pede cores agradáveis, ela define a razão de contraste, um valor único e reproduzível que qualquer ferramenta calcula da mesma forma, a partir das mesmas constantes.
A razão compara o brilho percebido de duas cores, texto e fundo, e devolve um número entre 1:1 e 21:1. Cores idênticas dão 1:1 (invisível); preto puro sobre branco puro dá o máximo, 21:1. Todo o resto fica no meio, e os limiares da WCAG dizem onde traçar a linha. Mas atenção desde já: esse número é honesto sobre luminância e mentiroso sobre percepção. Ele acerta a maioria dos casos e erra alguns de forma previsível, e a segunda metade deste guia é sobre esses erros.
A derivação: luminância relativa e a razão
A conta tem três etapas. Primeiro, cada canal sRGB (0–255) é normalizado para 0–1 e linearizado, desfaz-se a curva de transferência (a correção de gama) que a tela aplica, para voltar à luz física. Essa curva tem um joelho: abaixo de um limiar minúsculo ela é uma reta (divide por 12,92), acima dela é uma potência de expoente 2,4. Depois, os três canais lineares viram uma luminância relativa, com pesos bem diferentes por canal porque o olho enxerga o verde muito mais que o azul. Por fim, a razão combina as duas luminâncias somando 0,05 a cada uma.
lin(c) = c / 12.92 se c <= 0.03928
lin(c) = ((c + 0.055) / 1.055) ^ 2.4 caso contrario / otherwise
L = 0.2126 * R + 0.7152 * G + 0.0722 * B
contraste = (L_claro + 0.05) / (L_escuro + 0.05)- c
- valor do canal (R, G ou B) já normalizado para 0–1
- 0.03928
- o joelho da curva sRGB, verbatim do texto normativo da WCAG (a rigor o sRGB moderno usa 0,04045; a diferença some em 8 bits)
- 2.4
- expoente que desfaz a gama sRGB e devolve a luz linear
- 0.2126 / 0.7152 / 0.0722
- pesos de luminância de R, G e B (o verde domina; o azul quase não conta)
- 0.05
- reflexão ambiente presumida (flare de tela): sem ela, preto sobre preto daria divisão por zero
Repare no verde: ele pesa 0,7152, quase três quartos do brilho,, enquanto o azul pesa só 0,0722. É por isso que texto azul-vivo sobre fundo escuro costuma reprovar mesmo parecendo vibrante: ele contribui pouquíssimo para a luminância. E como a razão sempre coloca a cor mais clara em cima, a ordem texto/fundo não muda o número, o contraste de A sobre B é igual ao de B sobre A. Guarde essa simetria: ela é conveniente para calcular e, como veremos, é justamente um dos defeitos da fórmula. Se a relação entre canais, matiz e luminosidade ainda parece nebulosa, o guia de espaços de cor: HEX, RGB e HSL mostra como mexer no brilho sem quebrar o matiz.
Dois exemplos trabalhados: o cinza que reprova por um triz
Vamos derivar uma cor concreta até o número final. Tome o cinza #767676 como texto sobre fundo branco #FFFFFF, um tom que parece perfeitamente legível a olho nu e que a própria WCAG usa como exemplo de fronteira. Cada canal vale 0x76 = 118, então normalizamos 118/255 = 0,46275, aplicamos a linearização (o ramo da potência, porque 0,46275 > 0,03928) e chegamos à luminância. O branco tem os três canais em 1,0, logo sua luminância é 1,0.
// Exemplo 1, #767676 (texto) sobre #FFFFFF (fundo)
// Example 1, #767676 (text) on #FFFFFF (background)
Canal / channel: 0x76 = 118 -> 118 / 255 = 0.46275
0.46275 > 0.03928 -> ((0.46275 + 0.055) / 1.055) ^ 2.4 = 0.18116
L(#767676) = 0.2126*0.18116 + 0.7152*0.18116 + 0.0722*0.18116
= (0.2126 + 0.7152 + 0.0722) * 0.18116 = 0.18116
L(#FFFFFF) = 1.00000
contraste = (1.00000 + 0.05) / (0.18116 + 0.05)
= 1.05 / 0.23116 = 4.5422 -> 4.54:1
// 4.54 >= 4.5 -> PASSA no AA de texto normal (por uma unha)
// 4.54 >= 4.5 -> PASSES AA normal text (by a hair)Um passo mais claro, #777777, cai para 4,478:1, e aqui mora uma sutileza que separa quem entende a WCAG de quem decora. A norma manda não arredondar: 4,478 é menor que 4,5, então reprova, mesmo que sua cabeça queira arredondar para 4,48. O verificador vai além e trunca a exibição para 4,47, deixando explícito que está abaixo do piso. Ou seja: #777777 reprova no texto normal por centésimos, e escurecer um único passo até #767676 já cruza a linha. Para título grande, porém, os dois passam folgado, porque o piso cai para 3:1.
| Cor do texto | Razão | Resultado |
|---|---|---|
| #777777 | 4,47:1 | Reprova no AA de texto normal (4,478 < 4,5); passa no grande e em UI. |
| #767676 | 4,54:1 | Passa no AA de texto normal por 0,04; reprova no AAA. |
| #666666 | 5,74:1 | Passa no AA; ainda reprova no AAA (< 7). |
| #595959 | 7,00:1 | Cruza o AAA, o cinza mais claro que ainda atinge 7:1 sobre branco. |
Ver os dados
| Categoria | Valor |
|---|---|
| Azul #00F sobre preto | 2,44:1 |
| Cinza #949494 sobre branco | 3,03:1 |
| Cinza #777 sobre branco | 4,47:1 |
| Branco sobre azul #0D6EFD | 4,5:1 |
| Cinza #767676 sobre branco | 4,54:1 |
| Cinza #666 sobre branco | 5,74:1 |
| Cinza #595959 sobre branco | 7:1 |
O gráfico deixa a lição visível: um azul saturado sobre preto (2,44:1) reprova em tudo apesar de parecer intenso, porque o azul quase não gera luminância; e há uma faixa estreita, entre 4,47 e 4,54, onde dois cinzas quase idênticos caem em lados opostos da linha de 4,5. Agora experimente reproduzir qualquer barra: informe as duas cores no verificador incorporado abaixo e leia a razão e o veredito para AA, AAA e componentes.
- Escolha as duas coresInforme a cor do texto e a do fundo em HEX, RGB ou nome CSS. Use o conversor de cores se precisar traduzir de um formato para outro.
- Leia a razão e o vereditoConfira se passa no nível e no tamanho de texto que você usa: AA normal (4,5), AA grande (3), AAA (7) ou UI (3).
- Ajuste se reprovarEscureça (ou clareie) o texto até cruzar o limiar; a ferramenta sugere um tom próximo que passa em 4,5:1, preservando o matiz.
Os limiares da WCAG 2.2 e sua história
Quatro critérios de sucesso da WCAG envolvem cor e contraste. O 1.4.3 Contraste (Mínimo) é nível AA e cobre texto (4,5:1 normal, 3:1 grande); o 1.4.6 Contraste (Aprimorado) é o AAA, mais rígido (7:1 normal, 4,5:1 grande); o 1.4.11 Contraste Não-textual (AA) exige 3:1 para bordas de campos, ícones essenciais, estados de foco e objetos gráficos; e o 1.4.1 Uso da Cor (nível A) proíbe usar a cor como único meio de transmitir informação. Texto grande recebe um piso menor porque letras maiores permanecem legíveis com menos contraste.
| Critério | Nível | Alvo | Aplica-se a |
|---|---|---|---|
| 1.4.1 Uso da Cor | A | Cor não pode ser o único indicador | Links, estados, gráficos, formulários |
| 1.4.3 Contraste (Mínimo) | AA | 4,5:1 normal · 3:1 grande | Texto e imagens de texto |
| 1.4.6 Contraste (Aprimorado) | AAA | 7:1 normal · 4,5:1 grande | Texto e imagens de texto |
| 1.4.11 Contraste Não-textual | AA | 3:1 | Componentes de UI e objetos gráficos |
- O que é texto grande
- Pela WCAG, pelo menos 18 pontos (com 1pt = 1,333px, isso é ~24px de CSS) em peso normal, ou 14 pontos em negrito (~18,5px). Abaixo disso, valem os limiares de texto normal. Como a escala de tipo hoje é fluida, veja CSS clamp e tipografia fluida para não cair sem querer abaixo do corte.
- Não arredonde a razão
- A WCAG é explícita: uma razão de 4,499:1 reprova no piso de 4,5:1. Por isso um cinza como #777777 (4,478) reprova, e por isso o verificador trunca a exibição em vez de arredondar para cima.
- AA vs AAA
- AA é o alvo prático da maioria dos sites e da maior parte das leis de acessibilidade. AAA é o ideal para conteúdo crítico, mas nem sempre é atingível em toda a interface, o próprio W3C não recomenda exigir AAA de um site inteiro.
- 1999WCAG 1.0
A primeira versão media cor por diferença de brilho e de matiz, não pela razão de luminância, um método hoje abandonado.
- 2008WCAG 2.0 introduz a razão
A recomendação define a luminância relativa e os critérios 1.4.3 (AA, 4,5:1) e 1.4.6 (AAA, 7:1). É a fórmula que ainda usamos.
- 2018WCAG 2.1 e o não-textual
Acrescenta o 1.4.11 Contraste Não-textual (3:1), estendendo a regra a bordas, ícones e estados de foco.
- 2023WCAG 2.2 e APCA fora do rascunho
A WCAG 2.2 vira recomendação sem mudar as fórmulas de contraste; no mesmo ano, a APCA é retirada do rascunho da WCAG 3 para mais avaliação.
Onde a fórmula erra, e o que é a APCA
A razão da WCAG 2.x é boa engenharia de 2008 e tem defeitos que hoje são bem documentados. Ela mede uma proporção de luminância, mas a legibilidade humana não é uma proporção pura: depende da polaridade, do tamanho e do peso da fonte, e do brilho ao qual o olho está adaptado. A fórmula não modela nada disso de forma contínua, então erra em duas direções, aprova combinações difíceis de ler e reprova algumas perfeitamente legíveis.
O segundo exemplo trabalhado mostra o defeito mais limpo: a cegueira à polaridade. Vimos que #767676 sobre branco dá 4,54:1 e passa no AA. Agora inverta, branco sobre um fundo #767676. A WCAG devolve exatamente o mesmo 4,54:1, porque a fórmula é simétrica: coloca a cor clara em cima e ignora quem é texto e quem é fundo. Só que, para o olho, texto escuro sobre fundo claro (polaridade positiva) costuma render melhor que texto claro sobre um cinza médio, na mesma diferença de luminância. Dois pares com o mesmo número, legibilidades diferentes, e a WCAG 2 não tem como expressar isso.
Aprova o ilegível: vermelho vivo sobre preto
Vermelho puro #FF0000 sobre preto dá 5,25:1 e passa no AA de texto normal. Mas vermelho saturado sobre preto vibra e cansa: o olho tem baixa acuidade para vermelho e azul puros, e a ausência de luminância de apoio faz as bordas tremerem. A WCAG só vê a proporção de luminância (o vermelho carrega 0,2126 dela) e não enxerga o custo perceptual da saturação. Aprovado no papel, sofrível na tela.
Reprova o legível: o buraco do modo escuro
Por causa do 0,05 e da forma da curva, a WCAG 2 comprime as diferenças no extremo escuro. Pares de texto claro sobre fundos escuros que um olho adaptado lê com conforto podem receber uma razão baixa e reprovar, enquanto outros pares escuros passam sem merecer. A pesquisa por trás da APCA nasceu justamente medindo essa discrepância: no escuro, a proporção de luminância deixa de prever a leitura real.
APCA e a WCAG 3: qual é o status real
A APCA (Accessible Perceptual Contrast Algorithm) é uma abordagem perceptual: em vez de uma proporção simétrica, produz um valor com sinal (Lc) que muda conforme a polaridade e casa com tabelas de tamanho e peso de fonte. Ela foi desenvolvida como candidata para o contraste da futura WCAG 3 (projeto Silver).
Seja honesto sobre o status: a APCA não é normativa em nenhum documento do W3C hoje. Em julho de 2023 o conteúdo de contraste visual (incluindo a APCA) foi retirado do rascunho da WCAG 3 para mais avaliação, e o rascunho atual afirma que o algoritmo de contraste da WCAG 3 ainda está indefinido. A WCAG 3 permanece rascunho de trabalho em 2026, com recomendação final projetada para não antes de 2028. Ou seja: a APCA não substituiu a WCAG 2, para conformidade e para a lei, a fórmula deste guia (4,5:1, 7:1, 3:1) é a que vale.
Contraste não resolve daltonismo
Passar no contraste é necessário, mas não suficiente. Cerca de 8% dos homens e 0,5% das mulheres de ascendência do norte europeu têm alguma forma de daltonismo vermelho-verde, o National Eye Institute resume como cerca de 1 em cada 12 homens. A herança é ligada ao cromossomo X: o homem tem um só X, então um gene defeituoso já basta; a mulher tem dois e o segundo costuma compensar, por isso a prevalência despenca. Para essas pessoas, duas cores podem ter contraste alto entre si e mesmo assim ficarem indistinguíveis quando a informação depende só do matiz.
O caso clássico é um gráfico que separa ganho e perda só por verde e vermelho, ou um link que se diferencia do texto apenas por ser azul. Por isso o critério 1.4.1 Uso da Cor (nível A) exige que a cor nunca seja o único meio visual de transmitir informação: acrescente sublinhado ao link, um ícone à mensagem de erro, um rótulo à fatia do gráfico, um padrão à área preenchida. Teste como suas cores aparecem para protanopia, deuteranopia e tritanopia no simulador de daltonismo antes de fechar a paleta, e lembre que fotos também carregam cor: o guia de formatos de imagem para a web toca em perfis e gama, que afetam como a cor chega à tela.
- Texto de corpo atinge 4,5:1 (AA); títulos grandes, ao menos 3:1, sem arredondar para cima.
- Bordas de campos, ícones essenciais e estado de foco têm ≥ 3:1 (1.4.11).
- Nenhuma informação depende só da cor (1.4.1): há ícone, texto ou padrão de apoio.
- A paleta foi conferida em um simulador de daltonismo (protan, deuteran, tritan).
- Pares de modo escuro foram testados com olhos reais, não só com a razão da WCAG 2.
Perguntas frequentes
Qual é o contraste mínimo para texto?
O cinza #777 passa sobre fundo branco?
Ícones e bordas também precisam de contraste?
A APCA vai substituir a fórmula da WCAG 2?
Contraste bom já garante acessibilidade de cor?
Por que a fórmula soma 0,05 às luminâncias?
Trate contraste como número, não como estética: a razão (1:1 a 21:1) sai da luminância relativa, com 4,5:1 para texto normal, 3:1 para texto grande e componentes, 7:1 no AAA, e sem arredondar para cima. Mas conheça os limites da fórmula: ela ignora polaridade e trata tamanho em degraus, então aprova alguns pares ilegíveis e reprova outros bons. A APCA nasceu para corrigir isso, mas ainda é rascunho; a WCAG 2.2 é o que vale hoje. E cor nunca deve ser o único indicador, some ícone, texto ou padrão, e cheque a paleta em um simulador de daltonismo.
Fontes e referências
- W3C, WCAG 2.2, 1.4.3 Contraste (Mínimo)
- W3C, WCAG 2.2, 1.4.6 Contraste (Aprimorado)
- W3C, WCAG 2.2, 1.4.11 Contraste Não-textual
- W3C, WCAG 2.2, definição de luminância relativa
- W3C, WCAG 2.2, 1.4.1 Uso da Cor
- W3C, WCAG 3.0 (rascunho de trabalho): algoritmo de contraste indefinido
- National Eye Institute, Color Blindness