CSS color-mix()

Adam Argyle
Adam Argyle

A função color-mix() (link em inglês) de CSS permite misturar cores em qualquer um dos espaços de cores compatíveis diretamente do CSS.

Compatibilidade com navegadores

  • 111
  • 111
  • 113
  • 16,2

Origem

Antes de color-mix(), para escurecer, clarear ou diminuir a saturação de uma cor, os desenvolvedores usavam pré-processadores CSS ou calc() em canais de cores.

Antes com SCSS
.color-mixing-with-sass {
  /* Sass: equally mix red with white */
  --red-white-mix: color.mix(red, white);
}

A Sass fez um ótimo trabalho para ficar à frente das especificações de cores do CSS. Entretanto, não existe uma maneira real de misturar cores no CSS. Para chegar perto, você precisa fazer cálculos dos valores de cor parciais. Veja um exemplo reduzido de como o CSS pode simular uma mistura atualmente:

Antes com HSL
.color-mixing-with-vanilla-css-before {
  --lightness: 50%;
  --red: hsl(0 50% var(--lightness));

  /* add "white" to red
     by adding 25% to the lightness channel
  */
  --lightred: hsl(0 50% calc(var(--lightness) + 25%);
}

O color-mix() traz a capacidade de misturar cores ao CSS. Os desenvolvedores podem escolher o espaço de cores que vão misturar e o nível de dominante de cada cor na combinação.

Depois
.color-mixing-after {
  /* equally mix red with white */
  --red-white-mix: color-mix(in oklab, red, white);

  /* equally mix red with white in srgb */
  --red-white-mix-srgb: color-mix(in srgb, red, white);
}

É isso que queremos. Flexibilidade, potência e APIs completas. Curta,

Como misturar cores no CSS

O CSS existe em um mundo de vários espaços de cores e uma gama de cores e, por isso, não é opcional especificar o espaço de cores para mistura. Além disso, diferentes espaços de cores podem mudar drasticamente os resultados de uma mistura. Portanto, conhecer os efeitos de um espaço de cor ajuda você a conseguir os resultados necessários.

Para uma introdução interativa, use esta ferramenta color-mix(): - Explore os efeitos de cada espaço de cor. - Explorar os efeitos de interpolação de matiz ao fazer a mistura em um espaço de cores cilíndrico (lch, oklch, hsl e hwb). - Para mudar as cores que estão sendo misturadas, clique em uma das duas caixas de cores superiores. - Use o controle deslizante para alterar a proporção de mistura. - Código CSS color-mix() gerado disponível na parte inferior.

Misturando os vários espaços de cores

O espaço de cores padrão para mistura (e gradientes) é oklab. Ele fornece resultados consistentes. Também é possível especificar espaços de cores alternativos para personalizar a mix de acordo com suas necessidades.

Por exemplo, considere black e white. O espaço de cores que elas se misturam não fará tanta diferença, certo? Errado.

color-mix(in srgb, black, white);
color-mix(in srgb-linear, black, white);
color-mix(in lch, black, white);
color-mix(in oklch, black, white);
color-mix(in lab, black, white);
color-mix(in oklab, black, white);
color-mix(in xyz, black, white);
Sete espaços de cor (srgb, linear-srgb, lch, oklch, lab, oklab, xyz) mostram os resultados da mistura de preto e branco. Aproximadamente cinco tons são mostrados, demonstrando que cada espaço de cor vai se misturar a um cinza de maneira diferente.
Teste a demonstração

Essa ação tem um efeito incrível!

Use blue e white para outro exemplo. Escolhi essa opção especificamente porque é um caso em que a forma de um espaço de cor pode afetar os resultados. Nesse caso, a maioria dos espaços de cor fica roxo enquanto passa do branco para o azul. Ele também mostra como oklab é um espaço de cores tão confiável para combinação, que é o mais próximo das expectativas da maioria das pessoas de misturar branco e azul (sem roxo).

color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
Sete espaços de cor (srgb, linear-srgb, lch, oklch, lab, oklab, xyz), cada um com resultados diferentes. Muitos são rosa ou roxo, alguns ainda são azuis.
Teste a demonstração

Aprender os efeitos de um espaço de cores com color-mix() é um ótimo conhecimento para criar gradientes. A sintaxe da cor 4 também permite que os gradientes especifiquem o espaço de cores, em que um gradiente mostra a mistura em uma área do espaço.

.black-to-white-gradient-in-each-space {
  --srgb: linear-gradient(to right in srgb, black, white);
  --srgb-linear: linear-gradient(to right in srgb-linear, black, white);
  --lab: linear-gradient(to right in lab, black, white);
  --oklab: linear-gradient(to right in oklab, black, white);
  --lch: linear-gradient(to right in lch, black, white);
  --oklch: linear-gradient(to right in oklch, black, white);
  --hsl: linear-gradient(to right in hsl, black, white);
  --hwb: linear-gradient(to right in hwb, black, white);
  --xyz: linear-gradient(to right in xyz, black, white);
  --xyz-d50: linear-gradient(to right in xyz-d50, black, white);
  --xzy-d65: linear-gradient(to right in xyz-d65, black, white);
}
Gradientes preto a branco em espaços de cores diferentes.
Teste a demonstração

Se você está se perguntando qual espaço de cor é "o melhor", não existe um. É por isso que existem tantas opções! Também não haveria novos espaços de cor sendo inventados (consulte oklch e oklab) se um fosse "o melhor". Cada espaço de cor pode ter um momento único para brilhar e ser a escolha certa.

Por exemplo, se você quiser um resultado de mistura vibrante, use hsl ou hwb. Na demonstração a seguir, duas cores vibrantes (magenta e limão) são combinadas, e hsl e hwb produzem um resultado vibrante, enquanto srgb e oklab produzem cores insaturadas.

A combinação resulta conforme descrito no parágrafo anterior.
Teste a demonstração

Se você quiser consistência e sutileza, use o oklab. Na demonstração a seguir, que mistura azul e preto, hsl e hwb produzem cores excessivamente vibrantes e matiz alteradas, enquanto srgb e oklab produzem um azul mais escuro.

A combinação resulta conforme descrito no parágrafo anterior.
Teste a demonstração

Passe cinco minutos com o color-mix() playground testando diferentes cores e espaços para começar a conhecer as vantagens de cada espaço. Além disso, esperamos que aconteça mais orientações sobre os espaços de cores, à medida que nos ajustamos aos potenciais deles nas nossas interfaces do usuário.

Como ajustar o método de interpolação de matiz

Se você optou por misturar um espaço de cor cilíndrico, essencialmente, qualquer espaço de cor com um canal de matiz h que aceite um ângulo, será possível especificar se a interpolação vai ser shorter, longer, decreasing e increasing. Se você quiser saber mais, isso é bem abordado neste Guia de cores HD.

Confira o mesmo exemplo de mistura de azul com branco, mas desta vez, apenas nos espaços cilíndricos com diferentes métodos de interpolação de matiz.

A combinação resulta conforme descrito no parágrafo anterior.
Teste a demonstração

Aqui está outro Codepen que fiz para ajudar a visualizar a interpolação de matiz, mas especificamente para gradientes. Acredito que isso ajudará você a entender como cada espaço de cores produz o resultado de mistura quando a interpolação de matiz é especificada, faça um estudo.

Mistura com sintaxes de cores variadas

Até agora, misturamos principalmente cores de nomes CSS, como blue e white. A mistura de cores CSS está pronta para misturar cores de dois espaços de cores diferentes. Esse é outro motivo pelo qual é fundamental especificar o espaço de cores para a mistura, já que ele define o espaço comum para quando as duas cores não estão no mesmo espaço.

color-mix(in oklch, hsl(200deg 50% 50%), color(display-p3 .5 0 .5));

No exemplo anterior, hsl e display-p3 serão convertidos em oklch e, em seguida, misturados. Muito legal e flexível.

Como ajustar as proporções de mistura

Não é muito provável que você queira partes iguais de cada cor toda vez que misturar, como a maioria dos exemplos até agora mostrou. A boa notícia é que existe uma sintaxe para articular quanto de cada cor precisa ser vista na mistura resultante.

Para começar este tópico, aqui está uma amostra de mixes que são todos equivalentes (e da especificação):

.ratios-syntax-examples {
  /* omit the percentage for equal mixes */
  color: color-mix(in lch, purple, plum);
  color: color-mix(in lch, plum, purple);

  /* percentage can go on either side of the color */
  color: color-mix(in lch, purple 50%, plum 50%);
  color: color-mix(in lch, 50% purple, 50% plum);

  /* percentage on just one color? other color gets the remainder */
  color: color-mix(in lch, purple 50%, plum);
  color: color-mix(in lch, purple, plum 50%);

  /* percentages > 100% are equally clamped */
  color: color-mix(in lch, purple 80%, plum 80%);
  /* above mix is clamped to this */
  color: color-mix(in lch, purple 50%, plum 50%);
}

Acho que esses exemplos ajudam a esclarecer bem os casos extremos. O primeiro conjunto de exemplos mostra como 50% não é obrigatório, mas pode ser especificado opcionalmente. O último exemplo mostra um caso interessante em que, quando as proporções excedem 100% quando somadas, elas são igualmente fixadas no total de 100%.

Observe também que, se apenas uma cor especificar uma proporção, a outra será considerada o restante de 100%. Aqui estão mais alguns exemplos para ajudar a ilustrar esse comportamento.

color-mix(in lch, purple 40%, plum) /* plum assigned 60% */
color-mix(in lch, purple, 60% plum) /* purple assigned 40% */
color-mix(in lch, purple 40%, plum 60%) /* no auto assignments */

Esses exemplos ilustram duas regras: 1. Quando as proporções excedem 100%, elas são fixas e distribuídas igualmente. 1. Quando apenas uma proporção é informada, a outra cor é definida como 100 menos essa proporção.

A última regra é um pouco menos óbvia: o que acontece se as porcentagens forem fornecidas para ambas as cores e não totalizarem 100%?

color-mix(in lch, purple 20%, plum 20%)

Essa combinação de color-mix() resulta em transparência, 40%. Quando as proporções não totalizam 100%, a mistura resultante não será opaca. Nenhuma das cores será totalmente misturada.

Conjunto de color-mix()

Como em todo o CSS, o aninhamento é processado bem e como esperado. As funções internas serão resolvidas primeiro e retornarão os valores delas ao contexto pai.

color-mix(in lch, purple 40%, color-mix(plum, white))

Fique à vontade para aninhar o quanto for necessário para alcançar o resultado desejado.

Como criar um esquema de cores claras e escuras

Vamos criar esquemas de cores com o color-mix().

Um esquema de cores básico

No CSS a seguir, um tema claro e escuro são criados com base em uma cor hexadecimal da marca. O tema claro cria duas cores de texto azul-escuro e uma cor de superfície branca muito clara na superfície. Em seguida, em uma consulta de mídia de preferência escura, as propriedades personalizadas recebem novas cores para que o plano de fundo seja escuro e as cores do texto mais claras.

:root {
  /* a base brand color */
  --brand: #0af;

  /* very dark brand blue */
  --text1: color-mix(in oklab, var(--brand) 25%, black);
  --text2: color-mix(in oklab, var(--brand) 40%, black);

  /* very bright brand white */
  --surface1: color-mix(in oklab, var(--brand) 5%, white);
}

@media (prefers-color-scheme: dark) {
  :root {
    --text1: color-mix(in oklab, var(--brand) 15%, white);
    --text2: color-mix(in oklab, var(--brand) 40%, white);
    --surface1: color-mix(in oklab, var(--brand) 5%, black);
  }
}

Tudo isso é feito ao misturar branco ou preto em uma cor de marca.

.

Esquema de cores intermediário

Isso pode ser feito adicionando mais do que temas claros e escuros. Na demonstração a seguir, as mudanças no grupo de opções atualizam um atributo na tag HTML [color-scheme="auto"], que permite que os seletores apliquem condicionalmente um tema de cores.

.

Essa demonstração intermediária também mostra uma técnica de aplicação de temas de cores em que todas as cores do tema são listadas em :root. Isso facilita a visualização de todos e os ajustes, se necessário. Mais adiante na folha de estilo, você pode usar as variáveis conforme elas são definidas. Isso economiza a busca por manipulações de cores na folha de estilo, já que todas elas estão contidas no bloco :root inicial.

Casos de uso mais interessantes

Ana Tudor tem uma ótima demonstração com alguns casos de uso para estudo:

Como depurar color-mix() com DevTools

O Chrome DevTools tem excelente suporte para color-mix(). Ele reconhece e destaca a sintaxe, cria uma prévia da combinação ao lado do estilo no painel "Styles" e permite escolher cores alternativas.

Ela vai ficar mais ou menos assim no DevTools:

Captura de tela do Chrome DevTools inspecionando a sintaxe de mistura de cores.

Divirta-se!