CSS color-mix()

Adam Argyle
Adam Argyle

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

Compatibilidade com navegadores

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 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 cor.

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

O Sass fez um ótimo trabalho para se manter à frente da especificação de CSS de cores. No entanto, não há uma maneira real de misturar cores no CSS. Para chegar perto, você precisa fazer cálculos de valores de cor parciais. Confira um exemplo reduzido de como o CSS pode simular a mistura hoje:

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%);
}

color-mix() permite misturar cores no CSS. Os desenvolvedores podem escolher em qual espaço de cores eles vão misturar e como cada cor vai ser dominante na mistura.

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. APIs flexíveis, poderosas e completas. Curta,

Mistura de cores no CSS

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

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

Como misturar os vários espaços de cor

O espaço de cores padrão para mistura (e gradientes) é oklab. Ele fornece resultados consistentes. Você também pode especificar espaços de cores alternativos para adaptar a mistura às suas necessidades.

Por exemplo, black e white. O espaço de cores em que eles são misturados não faz muita 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 cores (srgb, linear-srgb, lch, oklch, lab, oklab, xyz) mostram os resultados da mistura de preto e branco. Aproximadamente cinco tons diferentes são mostrados, demonstrando que cada espaço de cor vai se misturar até mesmo ao cinza de maneira diferente.
Teste a demonstração

Isso tem um grande efeito.

Considere blue e white como outro exemplo. Escolhi isso especificamente porque é um caso em que a forma de um espaço de cores pode afetar os resultados. Nesse caso, a maioria dos espaços de cor fica roxa ao passar do branco para o azul. Ele também mostra como oklab é um espaço de cor confiável para mistura, é 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 cores (sRGB, linear-sRGB, lch, oklch, lab, oklab, xyz), cada um com resultados diferentes. Muitos são rosa ou roxo, alguns ainda são azuis.
Confira a demonstração

Aprender os efeitos de um espaço de cores com color-mix() é um ótimo conhecimento para criar gradientes. A sintaxe Color 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 de preto a branco em diferentes espaços de cor.
Teste a demonstração

Se você está se perguntando qual espaço de cores é "o melhor", não há um. É por isso que há 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 misturadas, e hsl e hwb produzem um resultado vibrante, enquanto s rgb e oklab produzem cores não saturadas.

Os resultados da mistura, conforme descrito no parágrafo anterior.
Veja a demonstração

Se quiser consistência e sutileza, use o oklab. Na demonstração a seguir, que mistura azul e preto, hsl e hwb produzem cores muito vibrantes e com matizes alterados, 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 espaço de jogo color-mix(), testando cores e espaços diferentes. Assim, você vai começar a ter uma ideia das vantagens de cada espaço. Também esperamos que mais orientações sobre os espaços de cor aconteçam à medida que nos ajustamos ao potencial deles em nossas interfaces do usuário.

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

Se você escolheu misturar um espaço de cores 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 para shorter, longer, decreasing e increasing. Confira mais informações sobre isso no guia de cores em alta definição.

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

Os resultados da mistura, conforme descrito no parágrafo anterior.
Teste a demonstração

Confira outro Codepen que fiz para ajudar a visualizar a interpolação de matiz, mas especificamente para gradientes. Acredito que isso vai ajudar você a entender como cada espaço de cores produz o resultado da mistura quando a interpolação de matiz é especificada. Estude o assunto!

Mistura com sintaxe de cores variadas

Até agora, usamos principalmente cores nomeadas do 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 é importante 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 mistura, como mostrado na maioria dos exemplos até agora. Temos boas notícias: há uma sintaxe para articular a quantidade de cada cor que deve aparecer na mistura resultante.

Para começar este tópico, confira um exemplo de mixagens 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%);
}

Esses exemplos ajudam a esclarecer 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 de quando as proporções excedem 100% quando somadas, elas são igualmente ajustadas para totalizar 100%.

Além disso, se apenas uma cor especificar uma proporção, a outra será considerada o restante de 100%. Confira mais alguns exemplos para 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: Quando as proporções excedem 100%, elas são limitadas e igualmente distribuídas. 1. Quando apenas uma proporção é fornecida, a outra cor é definida como 100 menos essa proporção.

A última regra é um pouco menos óbvia. O que acontece se as porcentagens for fornecidas para as duas cores e não somarem 100%?

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

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

Aninhando color-mix()

Como em todo CSS, o aninhamento é processado bem e conforme esperado. As funções internas são resolvidas primeiro e retornam os valores para o contexto pai.

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

Sinta-se à vontade para aninhar o quanto for necessário para conseguir o resultado que você quer.

Como criar um esquema de cores claras e escuras

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

Um esquema de cores básico

No CSS abaixo, um tema claro e escuro é criado com base na cor hexadecimal de uma marca. O tema claro cria duas cores de texto azul-escuro e uma cor de superfície de plano de fundo branca muito clara. Em seguida, em uma consulta de mídia de preferência escura, as propriedades personalizadas recebem novas cores para que o plano de fundo fique escuro e as cores do texto fiquem 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 misturando branco ou preto em uma cor da marca.

Esquema de cores intermediário

É possível ir além e adicionar mais temas além dos claros e escuros. Na demonstração a seguir, as mudanças no grupo de botões de opção atualizam um atributo na tag HTML [color-scheme="auto"], que permite que os seletores apliquem condicionalmente um tema de cores.

(link em inglês)

Esta demonstração intermediária também mostra uma técnica de aplicação de temas de cores em que todas as cores do tema estão listadas em :root. Isso facilita a visualização de todos juntos e ajusta se necessário. Posteriormente na folha de estilo, você poderá usar as variáveis conforme são definidas. Isso evita a necessidade de procurar manipulações de cor na folha de estilo, porque elas estão contidas no bloco :root inicial.

Mais casos de uso interessantes

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

Como depurar color-mix() com o DevTools

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

Ele vai ficar mais ou menos assim nas Ferramentas do desenvolvedor:

Uma captura de tela do Chrome DevTools inspecionando a sintaxe da mistura de cores.

Boa mistura, pessoal!