Artigo Build·Desenvolvimento·13 min de leitura

Contraste de Cores e Acessibilidade Web: Guia WCAG 2.2 Completo

Mais de 300 milhões de pessoas têm algum grau de deficiência visual. Garantir contraste adequado é requisito legal em vários países e melhora UX para todos. Veja critérios WCAG 2.2, fórmula da luminância, implementação em JS, APCA (WCAG 3), simulação de daltonismo e auditoria.

Vitor Morais

Por Vitor Morais

Fundador do MochaLabz ·

🎨

Converta e visualize suas cores

HEX, RGB, HSL e preview — escolha as cores certas para atingir contraste WCAG.

Usar conversor de cores →

Contraste de cores é um dos requisitos mais visíveis (e mais violados) de acessibilidade web. Pessoas com baixa visão, catarata, daltonismo ou simplesmente lendo em tela com brilho sob sol precisam de contraste adequado para ler. WCAG 2.2 define regras claras; novas especificações (APCA/WCAG 3) estão em desenvolvimento. Este guia cobre a teoria, a fórmula matemática, implementação em JavaScript, ferramentas de auditoria e os padrões práticos para dark mode e design responsivo.

Por que contraste importa

Mais de 300 milhões de pessoas no mundo têm deficiência visual significativa. Milhões mais enfrentam condições temporárias — sol forte na tela, olho cansado depois de 8h de trabalho, display de baixa qualidade. Contraste adequado:

  • Torna o texto legível para quem tem baixa visão.
  • Ajuda quem tem daltonismo (combinação cor + contraste).
  • Reduz fadiga visual em todos os usuários.
  • Funciona em condições adversas (sol, display de baixa qualidade).
  • É exigido por lei em muitos países (LBI, ADA, EAA).

O que é taxa de contraste

Taxa de contraste é a razão entre a luminância relativa de duas cores. Varia de 1:1 (sem contraste, mesma cor) a 21:1 (preto puro sobre branco puro, máximo possível em sRGB).

Escala de taxa de contraste 1:1 sem contraste (mesma cor) 2:1 muito fraco 3:1 mínimo para UI e texto grande (WCAG AA) 4.5:1 mínimo para texto normal (WCAG AA) 7:1 texto normal (WCAG AAA) 15:1 alto contraste 21:1 máximo (preto / branco)

Critérios WCAG 2.2 para contraste

Taxas de contraste mínimas por critério WCAG 2.2
CritérioNível AA (mínimo)Nível AAA (ideal)
Texto normal (< 18pt)4.5:17:1
Texto grande (≥ 18pt ou 14pt bold)3:14.5:1
Componentes de UI3:1
Elementos gráficos (ícones, charts)3:1
Texto inativo/desabilitadoIsentoIsento
LogotiposIsentoIsento
Texto decorativo puroIsentoIsento

AA ou AAA?

AA é o padrão legal e prático em quase todos os países. AAA é ideal mas nem sempre viável (7:1 limita muito a paleta). Use AA como piso obrigatório; busque AAA em textos longos e críticos (contratos, documentação legal).

Exemplos de combinações comuns

Taxa de contraste de combinações comuns
CritérioTexto / FundoTaxaAA NormalAAA Normal
Preto puro (#000) / Branco (#fff)Preto / Branco21:1
#333 / #fff#333 / #fff12.6:1
#555 / #fff (cinza médio)#555 / #fff7.46:1
#767676 / #fff (cinza claro)#767676 / #fff4.54:1
#999 / #fff (cinza muito claro)#999 / #fff2.85:1
#1a73e8 / #fff (Google blue)Google Blue / #fff4.58:1
#0066cc / #fff (azul escuro)#0066cc / #fff6.39:1
Branco (#fff) / #000 (dark mode)#fff / #00021:1
#e5e5e5 / #0f0f0f (dark mode soft)#e5e5e5 / #0f0f0f14.5:1

A fórmula WCAG 2: luminância relativa

A fórmula WCAG considera a luminância relativa (L) de cada cor em escala linear (não sRGB gamma), com pesos baseados em percepção humana (olho é mais sensível a verde que vermelho e azul):

PASSO 1 — Converter sRGB (0-255) para valor normalizado (0-1) s = canal / 255 PASSO 2 — Linearizar (remover gamma sRGB) linear = s ≤ 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ^ 2.4 PASSO 3 — Calcular luminância relativa L = 0.2126 · R_linear + 0.7152 · G_linear + 0.0722 · B_linear PASSO 4 — Calcular razão de contraste L1 = luminância da cor mais clara L2 = luminância da cor mais escura ratio = (L1 + 0.05) / (L2 + 0.05) (O +0.05 modela luz ambiente refletida na tela.)

Implementação em JavaScript

function hexToRgb(hex: string): [number, number, number] { const clean = hex.replace('#', ''); const full = clean.length === 3 ? clean.split('').map((c) => c + c).join('') : clean; return [ parseInt(full.slice(0, 2), 16), parseInt(full.slice(2, 4), 16), parseInt(full.slice(4, 6), 16), ]; } function relativeLuminance(hex: string): number { const rgb = hexToRgb(hex); const [r, g, b] = rgb.map((c) => { const s = c / 255; return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4; }); return 0.2126 * r + 0.7152 * g + 0.0722 * b; } export function contrastRatio(hex1: string, hex2: string): number { const l1 = relativeLuminance(hex1); const l2 = relativeLuminance(hex2); const lighter = Math.max(l1, l2); const darker = Math.min(l1, l2); return (lighter + 0.05) / (darker + 0.05); } export function passesWCAG( hex1: string, hex2: string, level: 'AA' | 'AAA' = 'AA', isLargeText = false, ): boolean { const ratio = contrastRatio(hex1, hex2); const required = level === 'AAA' ? (isLargeText ? 4.5 : 7) : (isLargeText ? 3 : 4.5); return ratio >= required; } // Uso contrastRatio('#000000', '#ffffff'); // 21 contrastRatio('#1a73e8', '#ffffff'); // 4.58 passesWCAG('#1a73e8', '#ffffff', 'AA'); // true (4.58 > 4.5) passesWCAG('#1a73e8', '#ffffff', 'AAA'); // false (< 7)

APCA: o futuro (WCAG 3)

APCA (Accessible Perceptual Contrast Algorithm) é o algoritmo proposto para substituir WCAG 2 na versão 3 do WCAG (ainda em draft em 2026). Diferenças principais:

  • Considera direção do contraste: texto claro sobre fundo escuro ≠ texto escuro sobre fundo claro (WCAG 2 trata igual).
  • Valores em Lc (Lightness contrast): -108 a +106, em vez de razão 1:1 a 21:1.
  • Escala de resposta por tamanho/peso de fonte — reconhece que fontes maiores/grossas precisam de menos contraste.
  • Reflete percepção humana com mais precisão, especialmente em cinzas e cores vibrantes.

Não migre ainda

APCA é interessante mas ainda não obrigatório. WCAG 3 está em draft há anos. Use WCAG 2.2 como padrão em 2026 e acompanhe APCA como futuro. Alguns design systems modernos (Adobe Spectrum, IBM Carbon) já usam APCA internamente, mas para conformidade legal, WCAG 2 ainda rege.

Daltonismo: contraste por si não basta

~8% dos homens e 0.5% das mulheres têm algum tipo de daltonismo. Os principais:

Tipos de daltonismo e impacto em design
CritérioPrevalênciaO que afeta
Deuteranopia / deuteranomalia~6% dos homensDificuldade em distinguir verde/vermelho
Protanopia / protanomalia~2% dos homensMenos sensível a vermelho
Tritanopia / tritanomaliaRaro (~0.01%)Dificuldade com azul/amarelo
AcromatopsiaMuito raroSem visão de cores (só tons de cinza)

Regra de ouro

Nunca transmita informação apenas por cor. Sempre combine com: ícone, texto, posicionamento, padrão visual. “Verde = OK, vermelho = erro” sem texto ou ícone é inacessível para 10% dos usuários.

Chrome DevTools: simulação de visão

Chrome DevTools → Menu ⋮ → More Tools → Rendering Emulate vision deficiencies: ⦿ No emulation ⦿ Blurred vision ⦿ Reduced contrast ⦿ Protanopia (vermelho-deficiência) ⦿ Deuteranopia (verde-deficiência) ← mais comum ⦿ Tritanopia (azul-deficiência) ⦿ Achromatopsia (sem cores) Teste seu site com deuteranopia ativo. Se não consegue distinguir elementos críticos, redesenhe.

Contraste em dark mode

Dark mode tem particularidades que vale conhecer:

  • Evite preto puro (#000) com branco puro (#fff): contraste 21:1 causa tensão visual e cansaço em sessões longas. Use quase-preto #0f0f0f a #1a1a1a e quase-branco #e5e5e5 a #f0f0f0.
  • Mesmo ratio ≥ 4.5:1 se aplica. Não existe “regra mais leve” para dark mode. Verifique sempre.
  • Cores vibrantes ficam mais intensas em fundo escuro. Um azul #1a73e8 que tem 4.5:1 em fundo branco precisa de outro valor em dark mode.
  • Teste dark mode com simulação de daltonismo: combinações diferentes, resultados diferentes.
/* Exemplos de paletas com bom contraste em dark mode */ :root { /* Light mode */ --bg: #ffffff; --text: #1a1a1a; /* 16.8:1 — AAA */ --text-soft: #4a4a4a; /* 9.0:1 — AAA */ --accent: #0066cc; /* 6.4:1 — AA */ } @media (prefers-color-scheme: dark) { :root { --bg: #0f0f0f; --text: #e5e5e5; /* 15.3:1 — AAA */ --text-soft: #a0a0a0; /* 6.9:1 — AA */ --accent: #4a9eff; /* 7.5:1 — AAA em dark */ } }

Ferramentas para testar contraste

Ferramentas de verificação de contraste
CritérioTipoPlataforma
WebAIM Contrast CheckerWebsitewebaim.org/resources/contrastchecker
Chrome DevTools (integrado)BrowserInspecionar → Painel Contrast
Axe DevToolsExtensãoChrome, Firefox — auditoria completa
LighthouseBrowserDevTools → Lighthouse → Accessibility
Colour Contrast AnalyserDesktopApp gratuito TPGi, eyedropper
Figma — Contrast pluginDesignDentro do Figma, verifica durante design
StarkFigma / SketchPlugin premium com simulação completa
Pa11yCLI / CIpa11y https://site.com — ideal em CI

Auditoria automatizada em CI

// jest + jest-axe — testa acessibilidade em componentes React import { render } from '@testing-library/react'; import { axe, toHaveNoViolations } from 'jest-axe'; expect.extend(toHaveNoViolations); test('página não tem violações de acessibilidade', async () => { const { container } = render(<MeuComponente />); const results = await axe(container); expect(results).toHaveNoViolations(); }); // Playwright + axe-core — testa sites ao vivo import { test, expect } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; test('home sem violações', async ({ page }) => { await page.goto('https://meusite.com'); const results = await new AxeBuilder({ page }).analyze(); expect(results.violations).toEqual([]); }); // Pa11y CI — CLI para rodar em pipeline npx pa11y https://meusite.com npx pa11y-ci --sitemap https://meusite.com/sitemap.xml

Como melhorar contraste de cores existentes

Se sua paleta atual não passa no WCAG, opções:

  1. Escurecer o texto (para fundo claro) ou clarear (para fundo escuro). Geralmente 10-20% é suficiente.
  2. Clarear o fundo (para texto escuro) — geralmente preferível em design.
  3. Aumentar tamanho / peso da fonte: texto grande (18pt+ ou 14pt+ bold) só precisa de 3:1.
  4. Adicionar text-shadow sutil se fundo é imagem: text-shadow: 0 0 4px rgba(0,0,0,0.5).
  5. Overlay semi-transparente em texto sobre imagem: rgba(0,0,0,0.5) entre imagem e texto.
  6. Repensar a paleta: às vezes a cor principal não precisa ser texto. Use como background de badge ou borda.

Dicas práticas de design acessível

Checklist além do contraste

  • Nunca transmita informação APENAS por cor — use ícone, texto, posicionamento.
  • Links devem ter indicação além da cor: sublinhado, negrito, ou borda.
  • Estados (hover, focus, active) devem ter contraste adequado também.
  • Texto sobre imagens: overlay escuro semi-transparente garante contraste.
  • Placeholder em campos deve ter contraste ≥ 4.5:1 — comum violação.
  • Botões desabilitados têm isenção WCAG, mas evite cinzas indistinguíveis.
  • Teste em display real (não só simulador) — brilho e calibração variam.
  • Teste com usuários reais, incluindo pessoas com baixa visão.

Erros comuns que violam contraste

Anti-padrões frequentes

  • Cinza claro (#999) sobre branco — super comum em placeholders, falha AA.
  • Cor primária da marca sem testar: #aabbcc pode parecer bonito no Figma e falhar em produção.
  • Estado disabled ilegível: usuário nem percebe que o campo existe.
  • Texto em botão gradiente: contraste varia conforme posição — verifique nas duas pontas.
  • Ícones coloridos sem label de texto: problema para daltônicos e leitores de tela.
  • Text-decoration: none em links: remove sinal visual além da cor.
  • Dark mode com text-muted quase invisível: teste sempre os dois modos.
  • Não testar focus ring: usuários de teclado precisam de contraste no estado focado.

Como projetar paletas acessíveis do zero

  1. Escolha cores da marca e teste em uso realista (texto, botão, background).
  2. Crie variações por luminosidade: 50, 100, 200, ..., 900 como Tailwind — permite escolher tom certo para cada combinação.
  3. Defina pares aprovados: “primary-500 + white”, “primary-700 + white”, “primary-100 + primary-900”.
  4. Teste cada par com contrastRatio() e documente no design system.
  5. Simule daltonismo para cada par crítico.
  6. Revise periodicamente quando adicionar novas cores ou ajustar existentes.

Checklist de acessibilidade de cores

  • ✅ Texto normal com contraste ≥ 4.5:1.
  • ✅ Texto grande com contraste ≥ 3:1.
  • ✅ UI / ícones / gráficos com contraste ≥ 3:1.
  • ✅ Testado com simulação de daltonismo (deuteranopia no mínimo).
  • ✅ Informação nunca transmitida apenas por cor.
  • ✅ Estados hover, focus, active com contraste próprio.
  • ✅ Placeholders com contraste adequado.
  • ✅ Dark mode testado separadamente.
  • ✅ Focus ring visível em todos os elementos interativos.
  • ✅ Auditoria Axe / Lighthouse / Pa11y em CI.
  • ✅ Design system documenta pares aprovados.
  • ✅ Texto sobre imagens tem overlay para garantir contraste.

Para entender formatos de cor usados (HEX, RGB, HSL), veja cores HEX, RGB e HSL no CSS; para montar paleta escalável com variáveis, paleta de cores com variáveis CSS.

Perguntas frequentes

Qual a taxa de contraste mínima exigida pelo WCAG?+

WCAG 2.2 AA (padrão legal na maioria dos países) exige: 4.5:1 para texto normal, 3:1 para texto grande (18pt+ ou 14pt+ bold) e 3:1 para componentes de UI e gráficos. WCAG AAA (ideal, não obrigatório) exige 7:1 para texto normal e 4.5:1 para texto grande. A nova WCAG 3 (em draft) usa algoritmo diferente (APCA) que considera percepção humana real.

Contraste é obrigatório por lei?+

No Brasil, a Lei Brasileira de Inclusão (LBI 13.146/2015) exige acessibilidade digital para sites governamentais e privados que prestam serviços ao público. WCAG 2.1 AA é o padrão de referência. Nos EUA, ADA Title III e Section 508 exigem conformidade similar. Em 2025, o European Accessibility Act tornou WCAG 2.1 AA obrigatório para todos os sites de e-commerce, bancos e serviços digitais na UE.

Por que preto sobre branco tem 21:1 e não 100:1?+

A fórmula WCAG usa luminância relativa, não valor de cor direto. A escala vai de 1:1 (mesma cor, sem contraste) a 21:1 (preto #000 sobre branco #fff). Valores são calculados considerando percepção humana aproximada, com pesos diferentes para cada canal RGB (R=0.2126, G=0.7152, B=0.0722) — porque o olho humano percebe verde como mais "brilhante" que vermelho, e vermelho como mais que azul.

O que é APCA e por que substituirá o WCAG 2?+

APCA (Accessible Perceptual Contrast Algorithm) é a nova fórmula proposta para WCAG 3 (ainda em draft em 2026). Diferenças: mede percepção real em vez de luminância pura, distingue texto claro sobre fundo escuro vs vice-versa (WCAG 2 trata igual), considera tamanho e peso da fonte na métrica. Resultado: valores diferentes de WCAG 2 para as mesmas cores. APCA ainda não é obrigatório; use WCAG 2.2 como padrão e acompanhe APCA como futuro.

Texto grande segundo o WCAG tem qual tamanho?+

Texto grande é ≥ 18pt (24px) em peso normal OU ≥ 14pt (18.66px) em peso bold. Tudo abaixo disso é considerado texto normal e exige 4.5:1 (AA). Textos grandes podem usar 3:1 porque o tamanho maior compensa um pouco a perda de contraste. Isso inclui H1, H2, botões de chamada grandes.

Como contraste funciona no dark mode?+

As mesmas regras se aplicam. Mas há uma armadilha: preto puro (#000) sobre branco puro (#fff) causa cansaço visual e "vibração" de alguns usuários (visão astigmática). O padrão moderno é usar quase-preto (#111, #1a1a1a) e quase-branco (#f8f8f8). Mantém contraste alto mas reduz tensão visual. Para dark mode específico, use fundo #0f0f0f a #1a1a1a com texto em #e5e5e5 a #f0f0f0.

Preciso testar com simulação de daltonismo?+

Sim, fortemente recomendado. ~8% dos homens e 0.5% das mulheres têm daltonismo (deuteranopia/protanopia mais comum). Informação transmitida APENAS por cor (verde = válido, vermelho = erro) é invisível para essas pessoas. Chrome DevTools tem simulação integrada (Rendering → Emulate vision deficiencies). Extensões como Colorblindly fazem o mesmo. Sempre combine cor com ícone, texto ou posicionamento.

Como checar contraste em todo o site de uma vez?+

Use Axe DevTools (extensão Chrome/Firefox) ou Lighthouse Accessibility audit — ambos listam problemas de contraste em todas as páginas. Para sites grandes, use Pa11y ou SiteImprove para crawl automático com relatório. Em CI, configure axe-core ou jest-axe nos testes para falhar builds com regressão de acessibilidade.

#acessibilidade#wcag#contraste#cores#apca#a11y#css#daltonismo#dark mode#axe

Continue lendo