Cor avançada: paletas, modo escuro e acessibilidade total
Objetivos deste capítulo
- Estender a paleta em escalas de tons coerentes
- Construir um modo escuro que não seja um simples negativo
- Garantir a acessibilidade para além do texto: daltonismo, não-texto, estados
Quando uma paleta encontra o mundo real
Dois feedbacks chegam na mesma manhã ao Studio Mango. O primeiro vem de um beta-tester da Sereno: «Sou daltónico e não vejo a diferença entre as vossas mensagens de sucesso e de erro.» O segundo vem do cliente: «Os meus utilizadores meditam à noite — precisamos de um modo escuro.» Dois pedidos diferentes, uma mesma lição: a paleta do capítulo 2, perfeita em condições ideais, tem agora de enfrentar a diversidade real dos olhos e dos contextos de uso.
Este capítulo completa a tua caixa de ferramentas de cor em quatro frentes: estender cada cor em escala de tons (porque oito cores nunca chegam por muito tempo), raciocinar em luminosidade percecionada com OKLCH, construir um modo escuro digno desse nome, e levar a acessibilidade para além do contraste do texto — daltonismo, elementos não textuais, estados semânticos. No fim, já não entregarás uma paleta: entregarás um tema completo.
Das cores às escalas de tons
O teu token --color-primary é um tom único. Mas assim que a interface cresce, precisas das suas vizinhas: uma versão muito clara para um fundo de faixa, uma versão escura para o hover, uma versão quase preta para texto sobre fundo claro. Em vez de improvisar essas variantes caso a caso, os design systems profissionais definem uma escala de 9 a 11 tonalidades por tom, numeradas de 50 (a mais clara) a 900 (a mais escura).
Cada número tem um papel convencional: 50-100 para os fundos tingidos subtis, 200-300 para as bordas e estados desativados, 500 como cor de base, 600-700 para os hovers e estados ativos, 800-900 para texto do tom sobre fundo claro. Esta convenção torna as decisões rápidas e coerentes: «a faixa de informação usa sage-50 no fundo e sage-800 no texto» compreende-se imediatamente, e o contraste fica quase garantido por construção — os extremos de uma escala bem feita passam AA entre si.
:root {
/* Escala sage — gerada com luminosidade percecionada regular */
--sage-50: #F2F6F4; /* fundos tingidos subtis */
--sage-100: #E1EAE6;
--sage-200: #C4D5CE; /* bordas, separadores */
--sage-300: #A3BDB3;
--sage-400: #7E9D91;
--sage-500: #4A7C6F; /* base: botões, links */
--sage-600: #3D685D; /* hover */
--sage-700: #32554C; /* ativo */
--sage-800: #27423B; /* texto tingido sobre fundo claro */
--sage-900: #1C302B;
}
/* Os papéis apontam para a escala — nunca o inverso */
:root {
--color-primary: var(--sage-500);
--color-primary-hover: var(--sage-600);
--color-primary-surface: var(--sage-50);
}Repara na arquitetura de dois andares do código acima: a escala em bruto (--sage-500) de um lado, os papéis funcionais (--color-primary) do outro, com os papéis a apontar para a escala. Esta indireção é a chave do modo escuro que vem mais abaixo: mudarás aquilo que os papéis designam, sem tocar nem na escala nem nos componentes.
OKLCH: raciocinar em luminosidade percecionada
Para gerar estas escalas, o formato de cor conta mais do que se julga. O HSL clássico tem um defeito conhecido: a sua «luminosidade» mente. Um amarelo e um azul a 50 % de luminosidade HSL não têm de todo a mesma claridade percecionada pelo olho — o amarelo parece brilhante, o azul escuro. Consequência: uma escala gerada em HSL tem degraus irregulares, e os rácios de contraste tornam-se imprevisíveis de um tom para outro.
O formato moderno OKLCH corrige isso: o seu eixo L mede a luminosidade tal como o olho a perceciona. Duas cores OKLCH com o mesmo L parecem realmente igualmente claras, seja qual for o tom. Para ti, é um superpoder prático: pede as tuas escalas «em OKLCH, com um passo de luminosidade regular», e todos os teus tons (sage, pêssego, vermelho de erro) terão tonalidades alinhadas — o 600 do verde e o 600 do vermelho oferecerão o mesmo contraste sobre fundo branco.
Estende o meu design system Sereno em escalas de tons completas: - para cada cor de base (sage #4A7C6F, pêssego #E8A87C, vermelho de erro #B5544D), gera uma escala de 10 tonalidades (50 a 900) em OKLCH com um passo de luminosidade percecionada regular - mantém o tom e ajusta sobretudo luminosidade e chroma: as tonalidades claras ligeiramente dessaturadas, as escuras ligeiramente mais saturadas - entrega para cada tonalidade: o valor oklch(), o fallback hex, e o rácio de contraste sobre branco E sobre #1A1F1D - termina com uma tabela das combinações garantidas AA: que número de texto sobre que número de fundo Formato: bloco :root CSS comentado.
O modo escuro não é um negativo
Primeira intuição a matar: o modo escuro não é a inversão da paleta clara. Inverter produz um fundo preto puro (#000) que faz vibrar o texto branco, cores saturadas que se tornam fluorescentes, e sombras invisíveis. Um bom tema escuro assenta em quatro princípios. Um: um fundo cinzento muito escuro tingido (para a Sereno, um cinzento-verde profundo como #141816), nunca preto puro. Dois: cores dessaturadas — sobre fundo escuro, a mesma saturação parece mais berrante, por isso desce-se o chroma um nível.
Três: a elevação pela claridade. Em modo claro, um cartão destaca-se pela sua sombra; em modo escuro, as sombras já não se veem — é a própria superfície que clareia ligeiramente (um cartão é um pouco mais claro do que o fundo, uma modal ainda um pouco mais). Quatro: o branco quebrado em vez de branco puro (#E8ECEA em vez de #FFFFFF), para reduzir a vibração nas longas leituras noturnas — precisamente o contexto de uso da Sereno.
E é aqui que a tua arquitetura de dois andares compensa: para criar o tema escuro, não tocas nem nos componentes nem na escala — re-declaras unicamente os papéis num bloco prefers-color-scheme: dark. --color-surface passa a apontar para o cinzento profundo, --color-primary para um sage-400 mais claro (porque sobre fundo escuro é a versão clara do tom que contrasta). Trinta linhas de CSS, e toda a interface muda.
/* Modo escuro: re-declaram-se os papéis, nada mais */
@media (prefers-color-scheme: dark) {
:root {
--color-surface: #141816; /* cinzento-verde profundo, nada de preto puro */
--color-surface-raised: #1E2421; /* elevação pela claridade */
--color-text: #E8ECEA; /* branco quebrado, nada de branco puro */
--color-text-muted: #9DABA5; /* re-verificado: 5.2:1 sobre surface */
--color-primary: var(--sage-400); /* versão clara do tom */
--color-primary-hover: var(--sage-300);
--color-primary-surface: #20302B;
--shadow-soft: none; /* a elevação substitui a sombra */
--shadow-raised: none;
}
}Gera o tema escuro completo da Sereno a partir dos meus tokens claros (abaixo): [cola aqui o teu bloco :root + as tuas escalas] Regras: - re-declara UNICAMENTE os papéis em @media (prefers-color-scheme: dark), sem tocar nas escalas nem nos componentes - fundo cinzento-verde profundo (nada de preto puro), texto branco quebrado (nada de #FFF) - dessatura ligeiramente os destaques, usa as tonalidades claras das escalas para o primary - substitui as sombras pela elevação: surface-raised mais clara do que surface - entrega o rácio de contraste de CADA combinação texto/fundo do tema escuro - assinala toda a combinação abaixo de 4,5:1 e propõe a correção
Daltonismo: nunca codificar a informação apenas pela cor
Voltemos ao beta-tester. Cerca de 8 % dos homens e 0,5 % das mulheres percecionam mal certas cores — na maioria das vezes a distinção vermelho/verde, exatamente o par que a Sereno usa para erro/sucesso. A regra de acessibilidade é absoluta: a cor nunca deve ser o único canal que transporta uma informação. Uma mensagem de erro vermelha deve também ser assinalada por um ícone, um prefixo textual («Erro:»), ou uma forma distinta. Um campo inválido deve ter uma borda mais espessa ou um ícone, não apenas uma borda vermelha.
O reflexo de verificação: pede à IA que simule. «Descreve esta interface tal como a veria uma pessoa deuteranope; lista cada sítio onde uma informação é transportada apenas pela cor.» Podes também fazer o teste mental dos níveis de cinzento: se toda a página passasse a preto e branco, os estados continuariam distinguíveis? Se sim, o teu design é robusto; se não, sabes o que duplicar com um ícone ou uma etiqueta.
WCAG para além do texto: o 3:1 dos elementos de interface
O capítulo 2 cobriu o texto (4,5:1). Mas as WCAG impõem também um mínimo de 3:1 para os elementos não textuais portadores de sentido: a borda de um campo de formulário (senão o campo é invisível), um ícone que serve de botão, o anel de focus, o estado marcado de uma checkbox, o traçado de um gráfico. É o ângulo morto de quase todas as paletas pastel — a borda cinzento-claro tão elegante da tua maquete faz provavelmente 1,8:1, e um utilizador com baixa visão simplesmente não encontra onde clicar.
Pensa também nos estados semânticos como pares completos: cada cor de estado (sucesso, erro, aviso, informação) existe em versão texto, versão fundo e versão borda — e cada combinação passa os seus patamares nos dois temas. É o momento em que o teu sistema deixa a «paleta bonita» para se tornar um verdadeiro tema de produção.
flowchart TD P["Paleta de base: papéis e tons"] --> E["Escalas 50 a 900 em OKLCH"] E --> T1["Rácios texto: 4,5 para 1 no mínimo"] E --> T2["Rácios não-texto: 3 para 1 no mínimo"] T1 --> D["Simulação daltonismo: informação nunca apenas pela cor"] T2 --> D D --> S["Tema escuro: papéis re-declarados e re-testados"] S --> V["Tema validado: light + dark documentados"]
Entregar um tema, não cores
Recapitulemos o entregável final para o programador da Sereno: as escalas de tons (a matéria-prima), os papéis funcionais em duas declarações (claro e escuro), os pares de estados semânticos completos, e um curto documento de uso — que número de escala para que uso, que combinações são garantidas, como acrescentar um tom sem partir o sistema. Acrescenta o respeito pela escolha do utilizador: o tema segue prefers-color-scheme por defeito, mas um interruptor manual deve poder forçá-lo, porque meditar à noite em modo claro forçado não é uma experiência premium.
O beta-tester daltónico receberá uma interface em que cada estado é duplicado por um ícone; o cliente terá o seu modo escuro digno de uma app de meditação noturna. E tu aprendeste a lição que vai além da cor: um design system não se julga em condições ideais, mas na diversidade real dos olhos, dos ecrãs e dos contextos que o vão encontrar.
Contexto
O cliente espera o modo escuro para a próxima release, e o feedback do beta-tester daltónico deve ser tratado na mesma passagem. Dispões dos teus tokens do capítulo 2 e de meio dia. O entregável: um tema claro + escuro completo, verificado para além do texto, com a sua documentação de uso para o programador.
Instruções
- Manda gerar as escalas de 10 tonalidades (50-900) em OKLCH para os teus três tons principais, com fallbacks hex e rácios de contraste.
- Reestrutura os teus tokens em dois andares: escalas em bruto de um lado, papéis funcionais do outro.
- Gera o tema escuro re-declarando unicamente os papéis: fundo tingido profundo, destaques dessaturados, elevação pela claridade.
- Exige os rácios em números de todas as combinações dos dois temas e manda corrigir tudo o que ficar abaixo de 4,5:1 (texto) ou 3:1 (não-texto).
- Faz a auditoria de daltonismo: pede a lista das informações transportadas unicamente pela cor, e duplica cada uma com um ícone ou uma etiqueta.
- Testa a landing completa nos dois temas (incluindo o formulário e os seus estados de erro) e redige as 10 linhas de documentação de uso.
Em resumo
- Uma cor de base torna-se uma escala de 9-11 tonalidades (50-900), cada número com um papel convencional.
- A arquitetura de dois andares — escalas em bruto, papéis funcionais que apontam para elas — torna os temas intercambiáveis.
- O OKLCH mede a luminosidade percecionada: escalas regulares e contrastes previsíveis de um tom para outro.
- O modo escuro não é um negativo: fundo tingido profundo, destaques dessaturados, elevação pela claridade, branco quebrado.
- Todos os contrastes devem ser re-testados em escuro — o texto atenuado é a armadilha clássica.
- A informação nunca deve ser transportada apenas pela cor: ícone, etiqueta ou forma em duplo canal (8 % dos homens são daltónicos).
- As WCAG impõem também 3:1 aos elementos não textuais: bordas de campos, ícones ativos, focus, estados.
Quiz — verifica a tua compreensão
1. Para que serve uma escala de tons (50 a 900)?
2. Qual é a vantagem do OKLCH sobre o HSL?
3. Como construir um bom modo escuro?
4. O que fazer por um utilizador daltónico que confunde as mensagens de erro e de sucesso?
5. Que rácio de contraste mínimo se aplica aos elementos não textuais portadores de sentido (bordas de campos, ícones ativos)?
6. Porquê re-testar todos os contrastes depois de criar o tema escuro?