Tutorials

CSS color-mix(): Misture Cores Nativamente no Navegador

9 min read

Por anos, gerar variantes de cores em CSS exigia codificar manualmente cada sombra ou recorrer ao JavaScript e a uma biblioteca de manipulação de cores como chroma.js ou tinycolor2. A função CSS color-mix() muda isso. É uma função CSS nativa, agora suportada em todos os principais navegadores, que mistura duas cores em uma proporção especificada — diretamente na sua folha de estilos, sem JavaScript, sem pré-processamento.

Este artigo abrange a sintaxe completa, explica por que a escolha do espaço de cores muda tudo, percorre os casos de uso práticos que tornam color-mix() genuinamente útil e aborda o suporte de navegadores e estratégias de fallback.

O que é color-mix()?

color-mix() é uma função CSS Color Level 5 que recebe dois valores de cor e uma proporção de mistura, e retorna a cor misturada resultante. É o equivalente CSS de misturar duas tintas juntas, mas com um parâmetro extra crítico: o espaço de cores em que a mistura ocorre.

O caso de uso mais simples é criar tintes e sombras a partir de uma cor base. Em vez de definir cada variante de sombra do seu azul de marca manualmente, você pode derivá-las dinamicamente:

:root {
  --brand-blue: #2563EB;

  /* Tintes — misturar com branco */
  --brand-blue-light:   color-mix(in oklch, var(--brand-blue) 60%, white);
  --brand-blue-lighter: color-mix(in oklch, var(--brand-blue) 30%, white);

  /* Sombras — misturar com preto */
  --brand-blue-dark:    color-mix(in oklch, var(--brand-blue) 80%, black);
  --brand-blue-darker:  color-mix(in oklch, var(--brand-blue) 50%, black);
}

O azul base #2563EB é definido uma vez. Os tintes e sombras são derivados dele. Se a cor da marca mudar, todas as variantes são atualizadas automaticamente.

Sintaxe e Parâmetros

A sintaxe completa de color-mix() é:

color-mix(in <color-space>, <color1> [<percentage>]?, <color2> [<percentage>]?)

O Parâmetro de Espaço de Cores

O primeiro argumento, in <color-space>, é obrigatório e especifica onde a mistura acontece. As opções válidas incluem:

  • srgb — mistura em RGB padrão (mais familiar, mas propenso a pontos médios opacos)
  • hsl — mistura seguindo o cilindro HSL
  • hwb — mistura em HWB (Matiz, Claridade, Negritude)
  • lab — mistura em CIE Lab (perceptualmente uniforme)
  • oklab — mistura em Oklab (melhor uniformidade do que o CIE Lab)
  • lch — mistura em LCH (CIE Lab cilíndrico)
  • oklch — mistura em OKLCH (Oklab cilíndrico, recomendado para a maioria dos usos)
  • display-p3 — mistura em Display P3 de gama ampla
  • xyz — mistura em CIE XYZ

Para a maioria do trabalho de design, oklch produz os resultados perceptualmente mais naturais. Mais sobre isso na próxima seção.

Os Argumentos de Cor

Os dois valores de cor podem ser qualquer cor CSS válida: códigos hex, rgb(), hsl(), oklch(), cores nomeadas ou propriedades personalizadas CSS. Cada um pode opcionalmente ter uma porcentagem indicando quanto aquela cor contribui para a mistura:

/* Mistura 50/50 (padrão quando nenhuma porcentagem é fornecida) */
color-mix(in oklch, #FF5733, #3498DB)

/* 70% da primeira cor, 30% da segunda */
color-mix(in oklch, #FF5733 70%, #3498DB 30%)

/* 80% da primeira cor — a porcentagem da segunda é inferida como 20% */
color-mix(in oklch, #FF5733 80%, #3498DB)

Se as porcentagens somarem menos de 100%, o resultado é parcialmente transparente. Se excederem 100%, as porcentagens são normalizadas. Se nenhuma porcentagem for especificada, a mistura é 50/50.

/* Estes são equivalentes */
color-mix(in srgb, blue, red)
color-mix(in srgb, blue 50%, red 50%)
color-mix(in srgb, blue 50%, red)

Misturando em Diferentes Espaços de Cores

A escolha do espaço de cores não é cosmética — ela muda fundamentalmente a cor produzida. As mesmas duas cores misturadas em espaços diferentes produzem resultados dramaticamente diferentes.

Misturando em sRGB

A mistura em sRGB funciona interpolando os canais de Vermelho, Verde e Azul linearmente. Para muitos pares de cores, isso produz resultados aceitáveis, mas cores complementares (aquelas em lados opostos da roda de cores) frequentemente produzem um ponto médio dessaturado e acinzentado.

/* Misturando laranja-avermelhado e azul em sRGB */
color-mix(in srgb, #FF5733 50%, #3498DB 50%)
/* Resultado: um roxo apagado, meio acastanhado — na faixa de [#9A77B7] */

O problema é que os canais RGB de cores complementares se cancelam ao serem calculados pela média. O Vermelho [255, 87, 51] e o Azul [52, 152, 219] produzem um ponto médio de [154, 120, 135] — um resultado dessaturado e acinzentado.

Misturando em HSL

A mistura em HSL interpola ao longo da roda de matiz, o que pode causar um problema diferente: rotação de matiz por cores intermediárias inesperadas.

/* Laranja (matiz ~15°) misturado com azul (matiz ~210°) em HSL */
color-mix(in hsl, #FF5733 50%, #3498DB 50%)
/* O matiz interpola por ~112° — você obtém um intermediário esverdeado */

Quando duas cores estão muito distantes na roda de matiz, o caminho mais curto entre elas em HSL pode passar pelo verde ou outros matizes inesperados. O HSL também compartilha o problema de não uniformidade perceptual do hsl() em geral — a luminosidade do ponto médio pode não parecer estar no meio das duas luminosidades de origem.

Misturando em OKLCH

A mistura em OKLCH é a abordagem recomendada para a maioria dos casos de uso práticos. Ela interpola em um espaço perceptualmente uniforme, o que significa que as cores intermediárias parecem pontos médios visuais naturais — vívidas, equilibradas e livres de desvio inesperado de matiz.

/* Laranja-avermelhado misturado com azul em OKLCH */
color-mix(in oklch, #FF5733 50%, #3498DB 50%)
/* Resultado: um magenta-roxo vívido — perceptualmente na metade do caminho */

#FF5733 (um laranja-avermelhado quente) e #3498DB (um azul brilhante) misturados 50/50 em OKLCH produzem um intermediário vibrante e saturado. O matiz interpola diretamente pela faixa de roxo — exatamente o que um designer esperaria ao "dividir a diferença" entre laranja e azul.

Misturando em Oklab (Caminhos de Matiz Mais Curtos / Mais Longos)

Para interpolação de matiz, você também pode especificar se deseja tomar o arco mais curto ou mais longo ao redor da roda de cores:

/* Caminho de matiz mais curto (padrão) */
color-mix(in oklch shorter hue, red, blue)

/* Caminho de matiz mais longo — vai pelo outro lado da roda */
color-mix(in oklch longer hue, red, blue)

/* Matiz crescente */
color-mix(in oklch increasing hue, red, blue)

Esse controle é útil quando você deliberadamente quer uma interpolação que passe por matizes intermediários específicos — por exemplo, um gradiente que vai do vermelho pelo amarelo até o azul em vez de passar pelo roxo.

Tabela de Comparação

Espaço de cores Ponto médio laranja + azul Caráter visual
srgb Roxo acinzentado apagado Dessaturado, baçante
hsl Esverdeado Desvio de matiz inesperado
lab Roxo, menos vívido Mais natural do que sRGB
oklch Magenta-roxo vívido Mais perceptualmente natural

Use o Conversor de Cores para explorar os valores OKLCH das suas cores específicas e prever como elas vão se misturar.

Casos de Uso Práticos

Criando Estados Hover e Ativo

Uma das aplicações mais imediatamente úteis é gerar estados interativos sem definir variáveis separadas para cada um:

:root {
  --btn-bg: oklch(0.55 0.22 250);  /* Seu azul de marca */
}

.btn {
  background-color: var(--btn-bg);
}

.btn:hover {
  /* Escurecer 15% misturando com preto */
  background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
}

.btn:active {
  /* Escurecer mais para o estado pressionado */
  background-color: color-mix(in oklch, var(--btn-bg) 70%, black);
}

.btn:disabled {
  /* Dessaturar e clarear para desativado */
  background-color: color-mix(in oklch, var(--btn-bg) 40%, white);
  opacity: 0.6;
}

Isso elimina a necessidade de escolher três sombras separadas em uma ferramenta de design e codificá-las rigidamente. As cores de hover e ativo são derivadas matematicamente da base, mantendo a relação consistente mesmo se a cor da marca mudar.

Criando Escalas de Cores Semânticas

Sistemas de design precisam de cores semânticas — sucesso, aviso, perigo — que se harmonizem com a paleta da marca. color-mix() permite derivar essas cores a partir da cor da marca em vez de escolhê-las de forma independente:

:root {
  --brand: oklch(0.55 0.22 250);  /* Azul de marca */

  /* Sucesso: misturar marca com verde puro para reter um toque de identidade da marca */
  --success: color-mix(in oklch, oklch(0.65 0.22 145) 85%, var(--brand) 15%);

  /* Aviso: âmbar puro — sem mistura necessária aqui */
  --warning: oklch(0.75 0.18 70);

  /* Perigo: vermelho puro */
  --danger: oklch(0.62 0.24 25);

  /* Fundos com tinte para cada estado */
  --success-bg: color-mix(in oklch, var(--success) 12%, white);
  --warning-bg: color-mix(in oklch, var(--warning) 12%, white);
  --danger-bg:  color-mix(in oklch, var(--danger)  12%, white);
}

O --success-bg é um tinte muito claro do verde de sucesso, derivado automaticamente. Use-os para banners de notificação, caixas de alerta e estados de erro em campos de formulário.

Gerando Escalas de Sombras Completas Dinamicamente

Embora o Gerador de Sombras seja a ferramenta certa para criar uma escala completa de 50 a 950 com passos perceptuais precisos, color-mix() pode gerar uma aproximação utilizável inline para componentes que precisam de um punhado de variantes:

:root {
  --primary: oklch(0.58 0.20 250);

  --primary-50:  color-mix(in oklch, var(--primary) 8%,  white);
  --primary-100: color-mix(in oklch, var(--primary) 15%, white);
  --primary-200: color-mix(in oklch, var(--primary) 30%, white);
  --primary-300: color-mix(in oklch, var(--primary) 50%, white);
  --primary-400: color-mix(in oklch, var(--primary) 70%, white);
  --primary-500: var(--primary);
  --primary-600: color-mix(in oklch, var(--primary) 85%, black);
  --primary-700: color-mix(in oklch, var(--primary) 70%, black);
  --primary-800: color-mix(in oklch, var(--primary) 55%, black);
  --primary-900: color-mix(in oklch, var(--primary) 35%, black);
  --primary-950: color-mix(in oklch, var(--primary) 20%, black);
}

Derivação de Cores para Modo Escuro

color-mix() é particularmente valioso para derivar cores de superfície do modo escuro de forma sistemática:

@media (prefers-color-scheme: dark) {
  :root {
    --surface-base:     #09090b;
    --surface-elevated: color-mix(in oklch, var(--brand) 8%, #09090b);
    --surface-overlay:  color-mix(in oklch, var(--brand) 12%, #09090b);
  }
}

Misturar uma pequena quantidade da cor da marca em superfícies escuras cria um tinte sutil — uma técnica usada pelo macOS da Apple e por muitos sistemas de design modernos para fazer o modo escuro parecer menos estéril do que superfícies neutras puras.

Comportamento do Canal Alfa

Quando as porcentagens não somam 100%, o resultado é parcialmente transparente. Isso pode ser usado deliberadamente para criar variantes translúcidas:

/* 30% de azul sobre uma base transparente — equivalente a rgba a 30% de opacidade */
color-mix(in srgb, blue 30%, transparent)

/* Também válido: transparência nomeada do outro lado */
color-mix(in oklch, #3B82F6 25%, transparent)

Isso substitui o padrão de usar rgba() com um alfa fixo. A vantagem é que a relação de opacidade é explícita na porcentagem de mistura, e você pode misturar com qualquer cor — não apenas transparência pura.

Suporte de Navegadores e Fallbacks

Em 2026, color-mix() é totalmente suportado em:

  • Chrome/Edge: desde a versão 111 (março de 2023)
  • Firefox: desde a versão 113 (maio de 2023)
  • Safari: desde a versão 16.2 (dezembro de 2022)

O suporte global supera 90%. Os usuários que não conseguem ver os resultados de color-mix() são aqueles em navegadores móveis muito antigos ou em ambientes corporativos com versões de navegador bloqueadas.

Fallback de Aprimoramento Progressivo

As declarações de propriedades personalizadas CSS são em cascata. Se o navegador não suportar color-mix(), o fallback na linha anterior é usado:

:root {
  /* Fallback para navegadores sem color-mix() */
  --btn-hover: #1D4ED8;

  /* Substituição com valor computado para navegadores modernos */
  --btn-hover: color-mix(in oklch, var(--btn-bg) 85%, black);
}

Como as propriedades personalizadas redeclaram a mesma variável, isso funciona como um padrão de aprimoramento progressivo. Os navegadores que não suportam color-mix() usarão a cor de fallback explícita; os navegadores modernos usarão o valor derivado.

Alternativamente, use @supports:

.btn:hover {
  background-color: #1D4ED8; /* Fallback */
}

@supports (color: color-mix(in oklch, red, blue)) {
  .btn:hover {
    background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
  }
}

A abordagem @supports é mais explícita e mais fácil de limpar quando você eventualmente abandonar o suporte a navegadores antigos.

Principais Conclusões

  • color-mix() mistura duas cores nativamente em CSS, eliminando a necessidade de JavaScript ou tabelas de sombras pré-geradas para muitos casos de uso.
  • O argumento in <color-space> controla onde a mistura acontece e afeta drasticamente o resultado. Use oklch para a maioria dos trabalhos — ele produz pontos médios perceptualmente naturais sem dessaturação baçante (problema do sRGB) ou desvios inesperados de matiz (problema do HSL).
  • Os casos de uso mais práticos são: estados interativos (hover, ativo, desativado), derivação de cor semântica, tingimento de superfície em modo escuro e geração de pequenas escalas de sombra a partir de uma única variável base.
  • Quando as porcentagens somam menos de 100%, a saída é parcialmente transparente — útil para criar variantes de opacidade sem rgba().
  • O suporte de navegadores cobre todos os navegadores modernos desde o início de 2023. Forneça um valor de fallback codificado na declaração CSS anterior ou dentro de um bloco @supports para ambientes mais antigos.
  • Use o Conversor de Cores para converter as cores da sua marca existentes para OKLCH antes de usá-las em color-mix(), e o Gerador de Paletas para visualizar relações de cores harmoniosas antes de escrever CSS.

Related Colors

Related Brands

Related Tools