Teoria das Cores no CSS Moderno: Dominando o color-mix() e Oklch

CSS Moderno · 12 min de leitura

Artigos › Teoria das Cores no CSS Moderno: color-mix() e Oklch

O Problema com o Modelo RGB na Web

Por décadas, o modelo RGB foi o único disponível para desenvolvedores web. rgb(255, 0, 0) é vermelho, #00FF00 é verde, e interpolações entre eles funcionavam razoavelmente bem — até você tentar fazer algo como um gradiente de amarelo para azul.

Tente este experimento: abra o DevTools, crie um gradiente linear-gradient(to right, yellow, blue) e observe o resultado. Você verá uma faixa cinza-esverdeada feia no meio. Isso não é um bug — é a matemática do espaço RGB funcionando exatamente como esperado. O problema é que "exatamente como esperado" não corresponde a como o olho humano percebe a mistura dessas cores.

O RGB foi criado para descrever sinais de hardware (intensidade de LEDs vermelho, verde e azul), não para modelar percepção humana de cor. O resultado é que operações que deveriam ser simples — como "tornar esta cor 20% mais clara" ou "misturar estas duas cores" — produzem resultados perceptualmente inconsistentes no RGB.

Mesmo gradiente amarelo → azul renderizado em três espaços de cor diferentes — veja a diferença diretamente no seu navegador:

sRGB
faixa cinza morta
OKLab
neutro e limpo
OKLCH
petróleo vibrante

O Que é OKLCH e Por Que os Olhos Preferem

OKLCH é um espaço de cor derivado do modelo Oklab (desenvolvido por Björn Ottosson em 2020), projetado especificamente para ser perceptualmente uniforme. Isso significa que uma mudança de 10 unidades em qualquer dimensão do espaço OKLCH produz uma mudança de contraste percebido equivalente — algo que o RGB simplesmente não garante.

O nome OKLCH descreve as três dimensões do espaço:

  • L (Lightness — Luminosidade): 0 = preto absoluto, 1 = branco absoluto. Diferente do HSL onde a luminosidade "percebida" do amarelo (L=50%) é muito diferente do azul (L=50%), no OKLCH o mesmo valor de L produz luminosidade percebida equivalente entre cores diferentes.
  • C (Chroma — Saturação): 0 = completamente dessaturado (cinza), valores maiores = mais vívido. Sem limite superior rígido — cores de alta saturação em displays modernos podem ter C > 0.4.
  • H (Hue — Matiz): Ângulo de 0 a 360 no espaço de cor, análogo ao H do HSL mas com distribuição perceptual uniforme.
L=0.2
L=0.3
L=0.4
L=0.5
L=0.6
L=0.7
L=0.78
L=0.86
L=0.93
/* Mesmo vermelho expressado nos três modelos */ color: rgb(255, 0, 0); /* RGB */ color: hsl(0, 100%, 50%); /* HSL */ color: oklch(0.6279 0.2576 29.23); /* OKLCH */

Luminância Perceptualmente Uniforme: Por Que Importa

O impacto mais prático da uniformidade perceptual do OKLCH está em sistemas de design com múltiplos tons de uma cor. Tente gerar uma escala de azul de 100 a 900 no HSL: o resultado frequentemente tem saltos perceptuais irregulares — o azul-500 parece muito diferente do azul-600, mas o azul-700 e 800 parecem quase idênticos.

Com OKLCH, você pode variar L em incrementos iguais (por exemplo, de 0.2 a 0.9 em passos de 0.1) e obter uma escala onde cada degrau parece igualmente distante do anterior. Isso simplifica enormemente a criação de sistemas de tokens de design consistentes.

color-mix() na Prática

A função color-mix(), disponível em todos os navegadores modernos desde 2023, permite misturar duas cores diretamente no CSS — sem JavaScript, sem pré-processadores.

Sintaxe Básica

/* Mistura 40% de azul em vermelho, no espaço sRGB */ color: color-mix(in srgb, red 40%, blue); /* Sem porcentagem explícita = 50/50 */ color: color-mix(in srgb, #FF6B00, #0070F3); /* Usando variáveis CSS */ color: color-mix(in oklch, var(--color-primary), transparent 30%);

Misturando em Espaços Diferentes: O Impacto no Resultado

A parte mais importante da sintaxe é o in [espaço]. A mesma mistura produz resultados radicalmente diferentes dependendo do espaço escolhido:

/* Amarelo + Azul: compare os resultados */ color: color-mix(in srgb, yellow, blue); /* → cinza-esverdeado feio */ color: color-mix(in hsl, yellow, blue); /* → verde vibrante */ color: color-mix(in oklch, yellow, blue); /* → azul-petróleo equilibrado */ color: color-mix(in oklab, yellow, blue); /* → cinza muito suave */

Para a maioria dos casos de uso em sistemas de design, in oklch produz os resultados mais naturais. Para gradientes, in oklab tende a eliminar a faixa cinza-morta que aparece no centro de gradientes RGB.

Aplicações práticas imediatas do color-mix():

  • Estados hover/focus sem JavaScript: background: color-mix(in oklch, var(--btn-bg) 85%, black); — um hover que escurece qualquer cor de botão de forma consistente.
  • Sombras coloridas: box-shadow: 0 4px 16px color-mix(in srgb, var(--brand-color) 40%, transparent);
  • Superfícies elevadas em dark mode: background: color-mix(in oklch, var(--surface) 92%, white);

Display P3 e HDR: O Futuro Próximo

Uma das razões pelo interesse crescente em OKLCH é sua capacidade de representar cores fora do gamut sRGB — o espaço de cor que limitou a web desde o início. O Display P3, suportado pela maioria dos iPhones e Macs desde 2016, consegue exibir aproximadamente 25% mais cores que o sRGB.

Com CSS moderno, você pode especificar cores P3 diretamente:

/* Cor P3 que não existe em sRGB */ color: color(display-p3 1 0 0); /* vermelho P3 — mais vibrante que #FF0000 */ /* Progressive enhancement */ color: rgb(255, 0, 0); /* fallback para sRGB */ color: color(display-p3 1 0 0); /* P3 para displays compatíveis */

Suporte a Navegadores e Progressive Enhancement

O suporte atual (maio 2026) para as tecnologias discutidas neste artigo:

  • OKLCH: Chrome 111+, Firefox 113+, Safari 15.4+. Suporte global acima de 90%.
  • color-mix(): Chrome 111+, Firefox 113+, Safari 16.2+. Suporte global acima de 90%.
  • Display P3: Chrome 111+, Firefox 113+, Safari 10.1+. Suporte global acima de 88%.

A estratégia recomendada para produção é o progressive enhancement: declare o fallback RGB/HEX primeiro, depois o valor moderno. Navegadores que não reconhecem a segunda declaração simplesmente a ignoram:

/* Progressive enhancement na prática */ .button { background: #6b7aa1; /* sRGB fallback */ background: oklch(0.55 0.09 263); /* OKLCH para navegadores modernos */ }

Explore nomes CSS e a função color-mix()

Para encontrar o nome CSS mais próximo de qualquer hexadecimal (útil para prototipagem rápida), use a Ferramenta de Nome CSS. Para entender em detalhes como o color-mix() funciona e ver exemplos de espaços de cor, veja o Glossário: color-mix().