Como criar um esquema de cores

Uma visão geral básica de como estabelecer um esquema de cores dinâmico e configurável

Nesta postagem, quero compartilhar ideias sobre maneiras de gerenciar vários esquemas de cores no CSS. Teste a demonstração.

Demonstração

Se você preferir o vídeo, aqui está uma versão do YouTube desta postagem:

Visão geral

Vamos criar um sistema de cores acessível com propriedades personalizadas e calc() para crie uma página da Web que se adapte às preferências do usuário, mantendo a criação experiência mínima. Começamos com uma cor de marca de base e criamos um sistema de duas cores de texto, quatro cores de superfície e uma sombra correspondente.

Este guia começa com a definição de todas as cores para cada esquema de cores frente. Só até o final eles são usados para alterar a página.

A marca

Muitas vezes, a cor de uma marca já foi estabelecida e é fornecida como hex ou rgb. Este desafio de GUI tem uma cor de marca base de #0af. Primeiro, para esse sistema de cores, o valor hexadecimal necessidades convertidas em hsl.

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

Para permitir um conceito de escurecer ou clarear a cor da marca, por exemplo, 20%, os 3 canais do valor de cor de hsl precisam ser extraídos para suas próprias , da seguinte forma:

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

O CSS pode fazer cálculos matemáticos nessas propriedades de cor, por exemplo, calc(var(--brand-lightness) - 20%) para diminuir o valor de brilho em 20%. Isso é fundamental para criar esquema de cores, pois o CSS pode manter todas as cores na mesma família de matiz ajustando o valores de saturação e luminosidade de hsl.

Tema claro

Cada variante de cor será marcada com o esquema correspondente. é anexado com -light.

visualização dos resultados finais do tema claro

Marca

Começando com a cor da marca, ele é recriado ao combinar --brand-hue e --brand-saturation. e --brand-lightness dentro do parêntese da função () de hsl, sem cálculos:

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}

Cores do texto

Em seguida, os fundamentos de um esquema de cores precisam de cores de texto. Em um tema claro, o texto deve ser muito escuro. Observe como o brilho das seguintes cores é baixo, bem abaixo de 50%.

* {
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
}

--text1-light, já que é muito escuro a 10% de iluminação, mantém a grossa 100% para que a cor da marca ainda apareça no azul-marinho escuro.

--text2-light, ela não é tão escura quanto a primeira cor, o que é bom, mas é uma cor secundária e também muito menos saturada.

Cores da superfície

As cores da superfície são os planos de fundo, bordas e outras superfícies decorativas que o texto fica sobre ou dentro dele. Em um tema claro, essas são as cores claras, em oposição às cores de texto, que eram escuras. Para criar cores claras com hsl, vamos usar valores percentuais mais altos no terceiro valor de iluminação. Também diminuiremos a saturação, para que os cinzas-claro não pareçam muito coloridos.

* {
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
}

Quatro cores de superfície foram criadas, já que cores decorativas tendem a precisar de mais variantes, para momentos interativos como :focus ou :hover, ou para criar a a aparência das camadas de papel. Nesses cenários, é bom fazer a transição --surface2-light ao passar o cursor para --surface3-light, ou seja, passar o cursor resulta em uma aumento do contraste (99% de claridade para 92% de claridade, tornando-o mais escuro).

Sombras

Sombras dentro de um esquema de cores estão acima e além, mas adicionam uma natureza realista ao o efeito e ajudá-lo a se destacar de sombras pretas irrealistas. Afazeres isso, a cor da sombra usará a propriedade personalizada matiz, será ligeiramente saturada de tonalidade, mas ainda muito escura. Basicamente, a construção de uma uma sombra levemente azul.

* {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

--surface-shadow-light não está encapsulado em uma função hsl. Isso ocorre porque o O valor --shadow-strength será combinado para criar alguma opacidade, e o CSS precisa as peças para realizar cálculos. Vá direto para a sombra radical para saber mais.

Cores claras em um só lugar

Não é preciso procurar para descobrir como as cores claras são feitas, elas são tudo em um só lugar no CSS.

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
  --surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
  --shadow-strength-light: .02;
}
captura de tela das cores claras juntas
Sandbox no CodePen

Tema escuro

A maioria das marcas não começa com um tema escuro, ele é uma variante do tema principal, geralmente um tema mais claro. Os usuários, por outro lado, geralmente escolhem um tema escuro para contextos diferentes, como a noite. Esses fatores me fizeram manter duas coisas em mente com os temas escuros:

  1. Os usuários geralmente ficam no escuro ao usar esse tema, então teste no escurecer.
  2. As cores devem diminuir a saturação para não vibrar na tela por serem excessivamente intensa.

prévia do resultado final do tema escuro

Marca

O tema claro usou os 3 valores dos canais de cor HDR da marca sem alteração, o tema escuro não. A saturação é reduzida pela metade e o brilho, em cerca de 50%.

* {
  --brand-dark: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 2)
    calc(var(--brand-lightness) / 1.5)
  );
}

Cores do texto

Em um tema escuro, as cores do texto precisam ser claras. As cores a seguir têm alto valores de claridade, colocando-os mais próximos do branco.

* {
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
}

Cores da superfície

Em um tema escuro, as cores da superfície precisam ser escuras. As cores a seguir têm pouca luminosidade e saturação, sendo que a 1a superfície é a mais escura a 10%.

* {
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
}

Sombras

Em um tema escuro, as sombras podem ser muito difíceis de enxergar. Faz sentido, já que é difícil escurecer algo que já é bastante escuro. É aqui que O --shadow-strength-dark é muito útil porque permite escurecer o as sombras, mudando uma variável.

* {
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}

Observe também o nível de saturação dessa sombra. Consegue notar a cor quando você está olhando para a interface? Tente remover a saturação do DevTools, qual você prefere?!

Cores escuras juntas

* {
  --brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}
captura de tela das cores escuras juntas
Sandbox no CodePen

Escurecer tema

Esse esquema de cores trata da orquestração de luminosidade e saturação. deve haver saturação suficiente para ainda ter uma matiz visível, mas também apenas passam as pontuações de contraste, já que é devem ser escuros e com baixo contraste.

visualização dos resultados finais do tema escuro

Marca

* {
  --brand-dim: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 1.25)
    calc(var(--brand-lightness) / 1.25)
  );
}

Cores do texto

* {
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
}

Cores da superfície

* {
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
}

Sombras

* {
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}

Escurecer todas as cores juntas

* {
  --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}
captura de tela das cores escuras todas juntas
Sandbox no CodePen

Cores acessíveis

Observe como o mínimo de brilho no conjunto de cores de texto escuro é de 65%, e o maior luminosidade em superfícies escuras é de 25%. Isso é 40% do brilho espaço entre eles. No tema claro, há 55% de espaço o tema claro. Manter as diferenças de claridade entre as cores do texto e da superfície entre 40 e 50% pode ajudar a manter altas taxas de contraste de cores, um elemento sutil para ajustar caso as pontuações sejam ruins.

Eu chamo de "bump bump til ya pass", que é a interação de bater no lightness até que uma ferramenta mostre que passei.

Shift + seta para baixo são pressionadas para diminuir o brilho e aumentar o contraste até passar

Todos os temas criados neste desafio são aprovados nas pontuações de contraste. O esquema de cores mais escuro tem o menor contraste entre elas, mas ainda atende aos requisitos mínimos. Para ajudar os outros membros da equipe a usar cores contrastantes, é uma boa ideia criar um nome de classe que combine uma cor de superfície com uma cor de texto acessível.

.surface1 {
  background-color: var(--surface1);
  color: var(--text2);
}

.surface2 {
  background-color: var(--surface2);
  color: var(--text2);
}

.surface3 {
  background-color: var(--surface3);
  color: var(--text1);
}

.surface4 {
  background-color: var(--surface4);
  color: var(--text1);
}
Captura de tela mostrando a superfície escura e os pareamentos de texto
Captura de tela da superfície escura e dos pareamentos de texto com o VisBug

Sombra radical

Os temas usam uma classe de utilitário chamada .rad-shadow. Esta sombra foi gerada ferramenta Smooth Shadow, que agradeço muito muito. Peguei o snippet gerado e o personalizei com minhas próprias cores e cálculos de opacidade. A razão disso foi criar uma sombra que eu pudesse ajustar dentro de cada esquema de cores.

cada sombra uma ao lado da outra

Para isso, criei duas variáveis para cada esquema de cores ajustar, uma cor da sombra e intensidade da sombra. A cor serve para saturação e escuridão ajustes, enquanto a intensidade serve como uma forma fácil de aumentar a sombra intensidade quando se tem um esquema de cores escuras. O resultado final ficou assim.

:root {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

.rad-shadow {
  box-shadow:
    0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
    0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
  ;
}

Se eu fosse além usando sombras no meu esquema de cores, eu faria a sombra uma constante de token de design, já que a direção da luz precisa ser a mesma entre todas as sombras do design.

Uso dos esquemas de cores

Com a predefinição das cores concluída, é hora de transformá-las propriedades independentes de esquema. O que quero dizer é, como um CSS nesse projeto de esquema de cores, raramente será necessário acessar uma o valor do esquema de cores específico. Quero facilitar a manutenção do tema.

Para isso, o uso do esquema de cores deve ser feito exclusivamente por meio de as propriedades personalizadas genéricas, que serão definidas em breve. Assim, As pessoas que usam as variáveis de design nunca precisam se preocupar com qual esquema de cores é definido no momento, basta usar as cores de superfície e texto. Em vez de color: var(--text1-light) usam color: var(--text1). Tudo sobre adaptação e mudança de cores é feito em um nível muito mais alto no CSS.

Os estilos de conexão do tema claro são abordados no bloco de código a seguir. conecta uma propriedade personalizada genérica com a cor específica do tema claro. Agora todos os usos de var(--brand) usarão a cor clara da marca.

Tema claro (automático)

:root {
  color-scheme: light;
  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

O site está usando o tema claro. Este é um momento de sucesso muito divertido! Vamos ter mais alguns desses momentos à medida que usamos nossas cores predefinidas em outros contextos de esquema de cores.

Tema escuro (automático)

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --brand: var(--brand-dark);
    --text1: var(--text1-dark);
    --text2: var(--text2-dark);
    --surface1: var(--surface1-dark);
    --surface2: var(--surface2-dark);
    --surface3: var(--surface3-dark);
    --surface4: var(--surface4-dark);
    --surface-shadow: var(--surface-shadow-dark);
    --shadow-strength: var(--shadow-strength-dark);
  }
}

Tema claro

[color-scheme="light"] {
  color-scheme: light;

  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

Tema escuro

[color-scheme="dark"] {
  color-scheme: dark;

  --brand: var(--brand-dark);
  --text1: var(--text1-dark);
  --text2: var(--text2-dark);
  --surface1: var(--surface1-dark);
  --surface2: var(--surface2-dark);
  --surface3: var(--surface3-dark);
  --surface4: var(--surface4-dark);
  --surface-shadow: var(--surface-shadow-dark);
  --shadow-strength: var(--shadow-strength-dark);
}

Escurecer tema

[color-scheme="dim"] {
  color-scheme: dark;

  --brand: var(--brand-dim);
  --text1: var(--text1-dim);
  --text2: var(--text2-dim);
  --surface1: var(--surface1-dim);
  --surface2: var(--surface2-dim);
  --surface3: var(--surface3-dim);
  --surface4: var(--surface4-dim);
  --surface-shadow: var(--surface-shadow-dim);
  --shadow-strength: var(--shadow-strength-dim);
}

Neste ponto, os autores estão livres para usar os genéricos de esquema de cores fornecidos como necessário e nunca mais deve se preocupar com temas.

Conclusão

Agora que você sabe como eu fiz isso, como faria?! 🙂

Vamos diversificar nossas abordagens e aprender todas as maneiras de criar na Web. Crie um Codepen ou hospede sua própria demonstração, envie um tweet para mim e eu a adicionarei ao seção "Remixes da comunidade" abaixo.

Origem

Remixes da comunidade - @chris-kruining adicionou um controle deslizante de matiz cores de status e modos de contraste para no-preference, more e less: demonstração.