Design

Contraste de cor e acessibilidade: o que a WCAG exige

Aquele cinza-claro elegante sobre fundo branco parece legível na sua tela nova, mas pode desaparecer para quem tem baixa visão, para quem lê sob sol direto ou num monitor barato. A WCAG resolve a discussão com um número objetivo: a razão de contraste, que vai de 1:1 (cores idênticas) a 21:1 (preto sobre branco). Este guia deriva esse número passo a passo, linearização do sRGB, luminância relativa, a constante 0,05,, fixa os limiares exatos de AA e AAA da WCAG 2.2, e depois faz o que a maioria dos textos evita: mostra onde a fórmula erra e por que existe uma sucessora, a APCA, que ainda não substituiu ninguém. Cole duas cores no [verificador de contraste](tool:verificador-contraste) enquanto lê, ele calcula tudo no navegador e sugere um tom próximo que passa quando o seu reprova.

J-Kit16 min de leituraIntermediário
  • Acessibilidade
  • WCAG
  • Contraste
  • Design
  • Cor

Resumo rápido

  • A razão de contraste vai de 1:1 (cores iguais) a 21:1 (preto sobre branco); para texto normal, o AA exige 4,5:1 e o AAA exige 7:1.
  • Texto grande (18pt ≈ 24px, ou 14pt em negrito ≈ 18,5px) e componentes de interface têm um piso menor, de 3:1.
  • A fórmula tem defeitos conhecidos: ignora a polaridade (claro-no-escuro vs escuro-no-claro) e trata tamanho/peso da fonte em degraus, não continuamente.
  • A APCA é a candidata perceptual para a WCAG 3, mas não é normativa em nenhum documento do W3C hoje, a WCAG 3 ainda é rascunho e diz que o algoritmo de contraste está indefinido.

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.

1:1Cores idênticas (mínimo)
4,5:1AA para texto normal
7:1AAA para texto normal
21:1Preto sobre branco (máximo)

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
Linearização de canal, luminância relativa e razão de contraste da WCAG 2.x, exatamente as fórmulas que o verificador implementa.

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)
Derivação completa de #767676 sobre branco: 4,54:1. Como R=G=B, os pesos somam 1 e a luminância é o próprio canal linearizado.

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.

Quatro cinzas sobre branco (#FFFFFF), com a razão exata que o verificador exibe.
Cor do textoRazãoResultado
#7777774,47:1Reprova no AA de texto normal (4,478 < 4,5); passa no grande e em UI.
#7676764,54:1Passa no AA de texto normal por 0,04; reprova no AAA.
#6666665,74:1Passa no AA; ainda reprova no AAA (< 7).
#5959597,00:1Cruza o AAA, o cinza mais claro que ainda atinge 7:1 sobre branco.
Azul #00F sobre preto2,44:1
Cinza #949494 sobre branco3,03:1
Cinza #777 sobre branco4,47:1
Branco sobre azul #0D6EFD4,5:1
Cinza #767676 sobre branco4,54:1
Cinza #666 sobre branco5,74:1
Cinza #595959 sobre branco7:1
Razão de contraste (calculada com a fórmula da WCAG) de combinações reais, contra os limiares 3:1 (grande/UI), 4,5:1 (AA texto) e 7:1 (AAA texto). Barras abaixo de 3 reprovam em tudo; entre 3 e 4,5 servem só a texto grande e componentes.
Ver os dados
CategoriaValor
Azul #00F sobre preto2,44:1
Cinza #949494 sobre branco3,03:1
Cinza #777 sobre branco4,47:1
Branco sobre azul #0D6EFD4,5:1
Cinza #767676 sobre branco4,54:1
Cinza #666 sobre branco5,74:1
Cinza #595959 sobre branco7: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.

Cole texto e fundo (HEX, RGB ou nome CSS): a ferramenta calcula a razão localmente, mostra AA/AAA/UI e sugere um tom próximo que passa em 4,5:1.Abrir a ferramenta em página inteira
  1. 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.
  2. 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).
  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.

Os critérios de sucesso relacionados a cor e contraste (WCAG 2.2).
CritérioNívelAlvoAplica-se a
1.4.1 Uso da CorACor não pode ser o único indicadorLinks, estados, gráficos, formulários
1.4.3 Contraste (Mínimo)AA4,5:1 normal · 3:1 grandeTexto e imagens de texto
1.4.6 Contraste (Aprimorado)AAA7:1 normal · 4,5:1 grandeTexto e imagens de texto
1.4.11 Contraste Não-textualAA3:1Componentes 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.
  1. 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.

  2. 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.

  3. 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.

  4. 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?
Para texto normal, a WCAG 2.2 exige 4,5:1 no nível AA e 7:1 no AAA. Texto grande (18pt ≈ 24px, ou 14pt em negrito ≈ 18,5px) pede 3:1 no AA e 4,5:1 no AAA. A norma manda não arredondar: 4,499:1 reprova no piso de 4,5:1.
O cinza #777 passa sobre fundo branco?
Não para texto normal: #777777 sobre #FFFFFF dá 4,478:1, abaixo dos 4,5:1 exigidos (o verificador exibe 4,47, truncado). Ele passa apenas como texto grande ou componente de interface (limiar 3:1). Escurecer um passo até #767676 sobe para 4,54:1 e cruza o AA.
Ícones e bordas também precisam de contraste?
Sim. O critério 1.4.11 (Contraste Não-textual, nível AA) exige pelo menos 3:1 para componentes de interface essenciais, bordas de campos, ícones que carregam significado, indicadores de foco, e para objetos gráficos necessários à compreensão. Ele foi acrescentado na WCAG 2.1, em 2018.
A APCA vai substituir a fórmula da WCAG 2?
Talvez um dia, mas hoje não. A APCA é a candidata perceptual para a WCAG 3, porém não é normativa em nenhum documento do W3C. Em 2023 o conteúdo de contraste foi retirado do rascunho da WCAG 3, que declara o algoritmo ainda indefinido; a WCAG 3 segue em rascunho, sem recomendação antes de 2028. Para conformidade, use a WCAG 2.2.
Contraste bom já garante acessibilidade de cor?
Não. Duas cores podem ter contraste alto e ainda assim se confundir para quem tem daltonismo se a informação depende só do matiz, o que atinge cerca de 1 em 12 homens. O critério 1.4.1 exige uma pista adicional (ícone, texto, padrão) sempre que a cor carrega significado.
Por que a fórmula soma 0,05 às luminâncias?
O 0,05 representa a luz ambiente que a tela reflete: nenhum preto real é totalmente preto. Somá-lo às duas luminâncias evita divisão por zero e limita a razão a 21:1. O efeito colateral é que, no extremo escuro, esse termo domina e a razão perde resolução, a origem do desempenho fraco da WCAG 2 no modo escuro.

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

  1. W3C, WCAG 2.2, 1.4.3 Contraste (Mínimo)
  2. W3C, WCAG 2.2, 1.4.6 Contraste (Aprimorado)
  3. W3C, WCAG 2.2, 1.4.11 Contraste Não-textual
  4. W3C, WCAG 2.2, definição de luminância relativa
  5. W3C, WCAG 2.2, 1.4.1 Uso da Cor
  6. W3C, WCAG 3.0 (rascunho de trabalho): algoritmo de contraste indefinido
  7. National Eye Institute, Color Blindness