CSS color-mix()

Adam Argyle
Adam Argyle

A função CSS color-mix() permite misturar cores em qualquer um dos espaços de cores aceitos diretamente no CSS.

Compatibilidade com navegadores

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 16.2.

Origem

Antes do color-mix(), para escurecer, clarear ou desaturar 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,

Como misturar 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, use esta ferramenta color-mix(): - Explore os efeitos de cada espaço de cores. - 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. - O código CSS color-mix() gerado está disponível na parte de baixo.

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. Cerca de cinco tons diferentes são mostrados, demonstrando que cada espaço de cor vai se misturar a um 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. Muitas são rosas ou roxas, poucas 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 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 para branco em diferentes espaços de cor.
Teste a demonstração

Se você está se perguntando qual espaço de cor é "o melhor", não existe um. É por isso que há tantas opções. Também não haveria novos espaços de cores 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 verde-limão) são misturadas, e hsl e hwb produzem um resultado vibrante, enquanto srgb e oklab produzem cores não saturadas.

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

Se você quer 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.

Os resultados da mistura, 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 espere mais orientações sobre espaços de cores à medida que nos ajustamos ao potencial deles nas interfaces do usuário.

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

Se você escolheu misturar em um espaço de cor cilíndrico, basicamente qualquer espaço de cor com um canal de matiz h que aceite um ângulo, é possível especificar se a interpolação é 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, sempre que você misturar, você queira partes iguais de cada cor, como a 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 para quando as proporções excedem 100% quando somadas, elas são igualmente limitadas a um total de 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 */

Estes 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.

Aninhamento color-mix()

Como em todo o CSS, o aninhamento é processado corretamente e como 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 a seguir, 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 branco-claro. 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.

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

Mais casos de uso interessantes

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

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 de mistura de cores.

Boa mistura!