Desenvolvedores

Como calcular a taxa de contraste de cores (WCAG AA/AAA)

7 min de leitura

A taxa de contraste de cores mede o quanto uma cor de texto se destaca do fundo, em uma escala de 1:1 (cores idênticas) a 21:1 (preto puro sobre branco puro). O WCAG 2.1 define taxas mínimas para considerar um texto legível: 4,5:1 para texto normal no nível AA, o critério usado pela maioria das auditorias de acessibilidade e exigências legais.

A fórmula

A taxa vem da luminância relativa de cada cor, não de como a cor “parece” na tela. Quatro passos transformam um código hex em um valor de luminância:

  1. Separe o hex em R, G, B e divida cada valor por 255, para que cada canal fique entre 0 e 1.
  2. Lineariza cada canal. As telas não traduzem valores de cor em brilho de forma linear, então cada canal recebe correção gama: se o valor for ≤ 0,03928, divida por 12,92; caso contrário, aplique ((valor + 0,055) / 1,055) ^ 2,4.
  3. Pondere e some os canais na luminância relativa: L = 0,2126 × R + 0,7152 × G + 0,0722 × B. O verde recebe o peso maior porque o olho humano é mais sensível a ele; o azul recebe o menor.
  4. Divida a luminância mais clara pela mais escura, ambas somadas a 0,05: (L_clara + 0,05) / (L_escura + 0,05).

Esse + 0,05 final cumpre uma função: ele impede que a taxa dispare rumo ao infinito quando uma das cores se aproxima do preto, e é por isso que preto puro sobre branco puro fecha exatamente em 21:1, e não em um número muito maior.

Exemplo prático: #767676 sobre branco

Esse par cinza sobre branco aparece com frequência na documentação do WCAG porque fica bem em cima de um limite, o que o torna útil para calcular passo a passo.

Passo 1. #767676 em RGB é 118, 118, 118. Dividido por 255, dá 0,4627 em cada canal.

Passo 2. 0,4627 está acima de 0,03928, então linearize com a fórmula gama: ((0,4627 + 0,055) / 1,055) ^ 2,4 = 0,1810. Os três canais são iguais aqui, então esse valor vale para R, G e B ao mesmo tempo.

Passo 3. Luminância: L = 0,2126 × 0,1810 + 0,7152 × 0,1810 + 0,0722 × 0,1810 = 0,1810. A luminância do branco é 1,0 (cada canal lineariza para exatamente 1).

Passo 4. Taxa: (1,0 + 0,05) / (0,1810 + 0,05) = 1,05 / 0,2310 = 4,545, arredondado para 4,54:1.

Esse valor fica logo acima da linha de 4,5:1 do AA para texto normal, e também logo acima da linha de 4,5:1 do AAA para texto grande, mas bem abaixo dos 7:1 que o AAA exige para texto normal. Um único hex, três veredictos diferentes dependendo do tamanho do texto e do nível que você está mirando.

Como pares de cores comuns se saem na prática

ParTaxaAA normal (4,5:1)AAA normal (7:1)AA grande (3:1)AAA grande (4,5:1)
#AAAAAA sobre #FFFFFF2,32:1ReprovadoReprovadoReprovadoReprovado
#767676 sobre #FFFFFF4,54:1AprovadoReprovadoAprovadoAprovado
#2563EB sobre #FFFFFF5,17:1AprovadoReprovadoAprovadoAprovado
#333333 sobre #FFFFFF12,63:1AprovadoAprovadoAprovadoAprovado

Dois pontos chamam atenção nessa tabela. Primeiro, um azul de saturação média como #2563EB (cor comum de botões e links) passa no AA para texto de corpo, mas reprova direto no AAA, então um site que mira AAA para links precisa de um tom mais escuro. Segundo, o cinza-claro popular em torno de #AAAAAA, usado em placeholders, reprova todos os limites, incluindo o mínimo de 3:1 para texto grande, o que explica por que texto cinza “discreto” sobre fundo branco é um dos achados mais comuns em auditorias de acessibilidade.

Teste suas próprias cores

Digite dois valores hex abaixo para ver a taxa exata e quais níveis do WCAG elas atingem, ao vivo, sem upload nem ida ao servidor.

Um rápido raposa marrom pula sobre o cão preguiçoso

Um rápido raposa marrom pula sobre o cão preguiçoso

Taxa de contraste 21:1
Texto normal
AA
AAA
Texto grande
AA
AAA
Verificador de Contraste de Cores
Grátis, sem cadastro, funciona em qualquer dispositivo.
Abrir a ferramenta completa

Erros comuns

Esquecer que texto grande tem um limite menor. O WCAG define “texto grande” como 18pt (24px) peso normal ou 14pt (18,66px) negrito em diante. Um título de 24px precisa de apenas 3:1, não 4,5:1, então um design system que aplica a mesma regra de contraste a todos os tamanhos de texto acaba reprovando títulos que já estão dentro das regras.

Testar o contraste do texto, mas não o dos componentes de interface. O WCAG 1.4.11 define um mínimo separado de 3:1 para elementos não textuais, como bordas de botão, contornos de campos de formulário e ícones que carregam significado sozinhos. Um botão com contraste de texto perfeito de 7:1 ainda pode reprovar uma auditoria se a borda se misturar ao fundo.

Checar o contraste contra o fundo errado. Texto sobre uma foto, um gradiente ou uma sobreposição semitransparente não tem uma única cor de fundo, tem várias. A taxa só vale para o ponto exato amostrado; um gradiente claro no topo e escuro embaixo precisa ter o ponto mais crítico verificado, não a média.

Supor que cores de marca estão isentas. A logomarca em si é isenta das exigências de contraste, mas texto de corpo e de interface na cor da marca não é. Muitos azuis e vermelhos de marca que funcionam bem como detalhe no logo reprovam o 4,5:1 quando usados como texto de parágrafo de 16px sobre branco.

Perguntas frequentes

Qual é a diferença entre AA e AAA? O AA é o padrão referenciado pela maioria das exigências legais de acessibilidade (ADA nos EUA, EN 301 549 na UE), e é o que a maioria das auditorias verifica. O AAA é mais rígido e pensado principalmente para conteúdo voltado especificamente a usuários com baixa visão; o próprio WCAG reconhece que o AAA não é viável para todo tipo de conteúdo, então a maioria das organizações mira o AA de forma ampla em vez do AAA em tudo.

A taxa de contraste considera daltonismo? Não. Taxa de contraste mede luminância (brilho), não matiz, então ela acaba ajudando várias formas de daltonismo por não depender da capacidade de distinguir cores específicas. Mas não substitui um teste de daltonismo: duas cores podem ter um contraste excelente e ainda assim ser difíceis de diferenciar para alguém com daltonismo vermelho-verde, se a diferença entre elas estiver principalmente na matiz e não na luminosidade.

Por que preto puro sobre branco dá exatamente 21:1 e não um número mais redondo? A luminância do preto é 0 e a do branco é 1. Colocando esses valores na fórmula, o resultado é (1 + 0,05) / (0 + 0,05) = 1,05 / 0,05 = 21. O valor fecha em exatamente 21:1 por causa de como a constante +0,05 foi escolhida, não por coincidência ou arredondamento.

Um tema dark mode precisa de verificações de contraste separadas? Sim. Trocar um fundo claro por um escuro não preserva a taxa: texto branco sobre o azul da sua marca e texto azul da marca sobre um fundo quase preto são dois pares de luminância diferentes, com duas taxas diferentes, então cada tema precisa passar pelo verificador por conta própria, em vez de assumir que o resultado do modo claro ainda vale.

AcessibilidadeWCAGCSSCor
Verificador de Contraste de Cores
Agora experimente você mesmo na ferramenta completa.
Experimentar agora