O que fórmula de paleta OKLCH faz?
Os neutros de um produto (fundo de página, superfície de cartão, poços, linhas finas, quatro degraus de texto) geralmente são de 15 a 30 valores hexadecimais por tema, escolhidos a olho. Eles desviam, o modo escuro é um segundo conjunto escolhido manualmente, e ninguém sabe quais pares ainda passam no contraste. Substitua-os por uma fórmula:
token de superfície: L = papel + profundidade × n(topo) croma = matiz matiz = matiz
token de tinta: L = tinta + passo × n(topo) croma = matiz-tinta matiz = matiz
n(topo) é a posição do token em uma escada, uma escada por tema.
Mova uma entrada e toda a rampa se move junto, então as lacunas entre os degraus,
que é onde o contraste vive, sobrevivem a uma retintagem. Retintar um produto é uma
linha (--matiz).
Três botões (--matiz, --luminosidade, --croma ou --contraste) controlam cada
cor.
Arquivos
references/palette.css: regras prontas para uso com entradas e escadas iniciais.scripts/fit_palette.py: ajusta as entradas a uma paleta hexadecimal existente e imprime ΔE por token.scripts/ladders.json: as escadas padrão (claro, escuro).scripts/palette-audit.mjs: resolve cada token em um navegador real em ambos os temas e falha no contraste.scripts/oklch.py: conversões e ajudantes ΔE / WCAG.
Procedimento
-
Nomeie os tokens pela função, não pelo valor. Os padrões:
- Fundos:
ground(página),panel(barras, barras de ferramentas),surface(cartões, menus),surface-2(poços),surface-3(chips, linhas destacadas),field. - Linhas:
line,line-2,line-3(linhas finas, do mais claro ao mais escuro), maisfield-line, a borda de um controle, que deve atingir 3:1. - Tinta:
ink,ink-2,ink-3,ink-4(texto, do mais escuro ao mais silencioso). Cada degrau de tinta é texto, então cada um deve atingir 4,5:1.
- Fundos:
-
Ajuste, não escolha novamente. Para um produto existente, execute
python3 scripts/fit_palette.py theme.css. Ele lê as declarações hexadecimais--color-*(claro, em seguida a regra[data-theme="dark"]), ajusta as entradas contra a escada padrão e imprime ΔE por token. Abaixo de 2 é visualmente idêntico. -
Substitua os degraus da escada onde o design os espaça de forma diferente, nunca a cor. Avalie candidatos com
fit_palette.py theme.css light '<inputs>' '<overrides>'até que o pior ΔE esteja abaixo de ~2. Substituições típicas:field: 0(campos são a face do cartão), umaline-3mais larga, um intervalo maior entreinkeink-2. -
Escreva as regras (veja
references/palette.css):- Coloque as entradas e as fórmulas
--color-*no elemento que carrega o atributo de tema. - Reafirme cada entrada que você alterar na regra escura. Uma regra escura escrita para os padrões do kit, caso contrário, ganha com seus valores.
- Com Tailwind v4, mantenha os nomes dos tokens em
@themepara que as utilidades existam; as declarações em tempo de execução as sobrescrevem.
- Coloque as entradas e as fórmulas
-
Audite em um navegador real:
node scripts/palette-audit.mjs <url>. Ele pinta cada token, lê de volta o sRGB e verifica:- cada degrau de tinta a 4,5:1 contra cada fundo;
field-lineeringa 3:1.
Corrija uma FALHA movendo o degrau da escada daquele token, não especializando uma cor. Espere FALHAS em paletas existentes: em uma migração de 17 aplicativos, a auditoria encontrou valores de
ink-4oufield-linefalhando em mais da metade deles, todos já lançados anteriormente.
Armadilhas
var()dentro de uma propriedade personalizada resolve onde é declarada.- Declare as fórmulas em
:roote defina entradas em um filho: o filho nunca recoloriza. - Tokens de alias (
--color-heading: var(--color-ink)) devem ser declarados no mesmo elemento com tema também.
- Declare as fórmulas em
- Os valores de
@themedo Tailwind v4 vivem em:root. Um tema com escopo em uma raiz de aplicativo ([data-app]) deve declarar a fórmula lá, não em@theme. - Qualquer coisa que entregue cores a uma tela ou biblioteca de mapas
(
getComputedStyle(...).getPropertyValue('--color-x')) agora recebe uma stringoklch(calc(...))não resolvida. Resolva-a primeiro: pinte um elemento sonda e leia uma tela de 1px, da mesma forma que a auditoria faz. - Um matiz para fundos e tintas. Se as tintas do design carregam um matiz diferente
de seus fundos, mantenha
--ink-tintbaixo; em L 0,98 qualquer croma parece um tom de cor. - Cores de marca, status e gráfico ficam fora da fórmula. Derive
variantes de texto sobre tom (por exemplo
brand-text) a partir do mesmo matiz a uma luminosidade fixa em vez de escolhê-las separadamente. - Paletas com matiz misto e apenas modo claro amostradas de composições podem não se ajustar dentro de ~2 ΔE. Pule-as em vez de distorcer o design. A auditoria ainda se aplica.