Cores
Um sistema de cores é um conjunto pequeno de rampas, nomeadas por função e verificadas em relação aos fundos sobre os quais realmente são renderizadas. A maioria dos bugs de cor são bugs de sistema. Um valor escolhido isoladamente, um token emprestado porque parecia certo, um par que ninguém mediu.
Nunca reporte um valor de contraste que você não mediu, e nunca estime uma cor que você poderia calcular. Cores são uma das poucas preocupações de interface com uma resposta exata, então produza a resposta exata.
Requisitos de contraste pertencem a hr-better-accessibility. Superfícies, sombras e cor de ícone estão fora deste skill.
Corresponda ao sistema de cores do projeto
Reutilize os tokens e a notação do projeto. Uma segunda representação adicionada para corrigir um valor torna a paleta mais difícil de raciocinar. Um sistema hex consistente supera hex com oklch() espalhado por ele.
Uma vez que os tokens existem, imponha-os com uma regra de lint ou teste de guarda que falhe em um literal de cor fora dos arquivos de token, com uma lista de permissões curta para lugares que precisam de valores brutos por design. Uma regra escrita "use tokens" sem nenhuma verificação por trás dela se desvia.
Para um novo sistema, oklch() é o melhor padrão, porque seus números se comportam da maneira que as regras de rampa abaixo descrevem. Em todos os outros lugares, uma biblioteca de cores produz a mesma rampa na própria notação do projeto (color-formats.md).
Um sistema é rampas, não cores
Uma rampa neutra, uma rampa de destaque e apenas as rampas de status que o produto realmente renderiza. Uma rampa warning que nada importa é manutenção para zero pixels. Um segundo matiz de destaque ganha seu lugar apenas quando duas coisas precisam ser distinguíveis rapidamente.
Cada degrau tem um trabalho
Uma rampa não é um gradiente para escolher a olho nu. Cada degrau existe porque uma função precisa dele: fundo de página, hover de componente, borda, preenchimento sólido, texto do corpo. Não gere um degrau que nenhuma função consome. Tanto as convenções 50–950 do Tailwind quanto 1–12 do Radix mapeiam para essas funções (palette-structure.md).
Nomeie primitivas por matiz, semânticas por função
Primitivas nomeiam um valor (--blue-500) e nunca são aplicadas em um componente. Tokens semânticos nomeiam um trabalho (--color-text-secondary), apontam para uma primitiva e são o único nível que os componentes referenciam.
Essa separação é o que torna a tematização possível. Sem ela, o modo escuro significa auditar cada uso para descobrir qual significava "o destaque" e qual apenas queria azul (token-naming.md).
Use um token apenas em sua função
Nunca pegue emprestado um token porque seu valor está certo hoje. Um separador usado como cor de texto funciona até que as bordas fiquem mais claras, e então o texto vai junto. Se uma função não tem token, adicione o token.
Mantenha o matiz ao longo da rampa
Quatro propriedades definem uma rampa bem formada:
- Os degraus seguem uma progressão de luminosidade percebida deliberada (palette-generation.md).
- O matiz permanece constante de ponta a ponta.
- A vivacidade atinge o pico no meio da rampa e diminui em ambas as extremidades.
- Os degraus são mais densos na extremidade clara do que na extremidade escura.
Ambas as extremidades param antes do preto e branco puros, que não conseguem carregar matiz algum. Use uma biblioteca de cores em vez de estimar a olho nu (palette-generation.md).
Uma cor, um significado
Use uma cor para um único propósito em toda a interface, tratando qualquer coisa dentro de 15° de matiz como a mesma cor. Se o destaque significa interativo, esse matiz em texto estático diz aos usuários para clicar em algo que não é clicável, e um elemento interativo renderizado neutro engana igualmente. A cor nunca é o único portador de significado, o que é de responsabilidade de hr-better-accessibility.
Preencha exatamente uma ação por visualização
Quando a cor preenchida codifica ênfase primária, uma ação primária a recebe e as iguais permanecem neutras. Coloque a cor no fundo, não no rótulo. Um botão preenchido parece primário do outro lado da sala; texto com cor de destaque em um botão neutro parece um link.
Vários fundos coloridos são aceitáveis quando codificam estados ou categorias distintos, em vez de competirem como iguais.
Meça o par renderizado, depois reporte
Meça um primeiro plano contra o fundo sobre o qual ele realmente é renderizado, não o fundo da página. Quando um par falha, reporte o par, seu valor medido e o limite que ele perde, depois deixe as cores em paz. Elas são uma decisão de design. Altere-as apenas quando solicitado, e meça novamente após (contrast.md).
Escolha o espaço de interpolação de um gradiente
O espaço é uma aparência, não uma configuração de correção.
in oklabé o melhor padrão: brilho uniforme, sem surpresas de matiz.in oklchviaja ao redor da roda de matiz em vez de pelo meio, permanecendo vívido e varrendo todos os matizes entre os pontos. Use-o quando um gradiente de dois matizes ficar cinza no meio.- O padrão sRGB escurece e silencia o ponto médio. É o que a maioria das interfaces já tem, porque é o que você obtém sem pedir.
Veja color-usage.md.
Antes de finalizar
| Erro | Correção |
|---|---|
| Um valor bruto onde o projeto tem um token | Reutilize ou adicione o token de função, na notação do projeto |
Um valor oklch() isolado inserido em uma base de código hex | Mantenha a notação estabelecida a menos que uma migração esteja no escopo |
Uma primitiva como --blue-500 usada diretamente em um componente | Aponte um token semântico para ela |
Token nomeado por sua aparência (--color-blue-button) ou primeiro uso (--color-sidebar-gray) | Nomeie-o por sua função: --color-accent-solid, --color-bg-surface |
--color-primary significando a marca e --color-text-primary significando texto do corpo | Reserve accent para a marca; deixe primary significar "o mais proeminente de seu grupo" |
| Token semântico usado fora de sua função (separador como texto) | Adicione um token para a função ausente; nunca pegue emprestado por valor |
| Rampa construída variando a luminosidade HSL | Reconstrua com base na luminosidade percebida com um matiz constante |
| Rampa espaçada uniformemente em toda a faixa | Aperte a extremidade clara até que 50 e 100 sejam lidos como duas superfícies |
| Mesmo número de saturação reutilizado entre matizes | Corresponda à proporção do máximo de cada matiz, não ao valor bruto |
| Matiz de status que colide com o matiz de destaque | Mova-o até que destrutivo e primário sejam lidos separadamente lado a lado |
| Modo escuro feito invertendo mecanicamente a paleta clara | Inverta como ponto de partida, depois reduza a vivacidade, alargue a extremidade escura e verifique novamente cada par |
prefers-color-scheme definindo alguns tokens e uma classe .dark definindo outros | Escolha um mecanismo de alternância e use-o em todo o projeto |
| Contraste corrigido alterando o matiz | Altere a luminosidade, o canal ao qual o contraste responde |
| Cor P3 sem fallback sRGB | Declare o valor sRGB primeiro, depois substitua dentro de @media (color-gamut: p3) |
Relatório
Severidade. HIGH torna o conteúdo ilegível ou atribui uma cor semântica enganosa. MEDIUM é uma falha perceptível de tema, token ou gama. LOW é um polimento isolado.
Verificação. Sem um navegador: valores de token, a gama de cada cor declarada, ambos os blocos de tema presentes e o contraste calculado a partir do par de token declarado. Com um: o fundo realmente renderizado atrás do texto, incluindo opacidade e qualquer imagem abaixo dele, medido tanto no claro quanto no escuro. Um par com falha é relatado, não repintado. Relate cada verificação que você não pôde executar como Não verificado.
Formato. Agrupe as descobertas sob o princípio que cada uma viola, ordenado por severidade, uma linha por causa raiz listando cada local onde aparece:
| Severidade | Localização | Antes | Depois | Porquê |
|---|
Localização é caminho/para/arquivo:linha. Porquê nomeia o princípio e o impacto no usuário.
Relate Bloqueio quando qualquer HIGH permanecer, Aprovar caso contrário, deixando o restante na tabela como trabalho a fazer. Nunca Aprove cobertura que você não inspecionou. Sem nada a relatar, declare "Nenhuma descoberta de cor acionável" e relate a verificação.