Interpolação de Cores em CSS: Por Que o OKLCH Vence
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://colorfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://colorfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://colorfyi.com/entity//)
Use the native HTML custom element.
Toda vez que o CSS mescla duas cores — em um gradiente, em color-mix() ou em uma transição — ele realiza interpolação de cores: calculando valores intermediários entre uma cor de início e uma cor de fim. Durante a maior parte da história da web, esse cálculo acontecia no espaço de cores sRGB, e os resultados frequentemente eram opacos, dessaturados ou perceptualmente desiguais. Com o CSS moderno, agora você pode escolher o espaço de cores para interpolação. A escolha importa enormemente, e o OKLCH consistentemente produz os melhores resultados.
Este tutorial explica por que a interpolação RGB falha, onde o HSL fica aquém e por que o OKLCH é o padrão correto para gradientes e mistura de cores em 2024 e além.
O Problema da Interpolação RGB: Pontos Intermediários Opacos
Quando você escreve um gradiente CSS sem especificar um espaço de cores, o navegador interpola em sRGB — ele calcula cores intermediárias misturando linearmente os valores dos canais R, G e B de forma independente.
Isso parece razoável, mas falha gravemente quando os dois extremos passam pelo meio do cubo sRGB. Considere um gradiente do vermelho ao verde:
/* Padrão: interpola em sRGB */
background: linear-gradient(to right, #FF0000, #00FF00);
O ponto intermediário deste gradiente em sRGB é #808000 — um azeitona opaco. Matematicamente, RGB 128, 128, 0 está exatamente no meio entre vermelho e verde em valores de canal. Mas perceptualmente, parece nada com um ponto intermediário vibrante entre dois primários vívidos. O gradiente mergulha em um vale escuro e opaco antes de clarear do outro lado.
O problema fundamental é que sRGB não é perceptualmente uniforme. Passos numéricos iguais em R, G e B não correspondem a passos iguais em cor percebida ou brilho. O cubo sRGB foi projetado para hardware de exibição, não para a visão humana.
/* Você pode forçar sRGB explicitamente */
background: linear-gradient(in srgb, red, blue);
/* Ou use a sintaxe legada (mesmo resultado) */
background: linear-gradient(red, blue);
Ambos produzem os mesmos pontos intermediários dessaturados. O problema é o próprio espaço de cores, não a sintaxe.
O Problema do Gamma
Há outra sutileza: os valores sRGB são codificados em gamma. Valores sRGB brutos de 0,5 não correspondem a 50% da luz física emitida por um display. O ponto intermediário perceptual real de um gradiente precisa ser calculado na luz linear, não no sRGB codificado em gamma. O CSS nível 4 introduziu in srgb-linear para resolver isso:
background: linear-gradient(in srgb-linear, red, blue);
O sRGB linear é melhor do que o sRGB com gamma para transições de luminância, mas ainda não resolve os problemas de mudança de matiz e queda de saturação porque ainda é um espaço RGB retangular.
Mudanças de Matiz no HSL
O HSL foi introduzido como uma alternativa mais legível por humanos ao RGB. Sua representação cilíndrica — Matiz em um ângulo de 0–360, Saturação e Luminosidade como porcentagens — facilita o raciocínio sobre relações de cores. Mas a interpolação HSL tem seu próprio modo de falha característico: mudanças de matiz.
Quando você interpola entre duas cores HSL, o navegador percorre o arco mais curto do círculo de matiz. Se você for de um vermelho quente (hsl(10, 100%, 50%)) para um azul frio (hsl(220, 100%, 50%)), o caminho mais curto passa pelo roxo e violeta — o que pode ou não ser o que você quer.
Mas o problema mais profundo é que a Luminosidade do HSL não é perceptualmente uniforme. Um amarelo em hsl(60, 100%, 50%) parece dramaticamente mais brilhante do que um azul em hsl(240, 100%, 50%), mesmo que compartilhem o mesmo valor L. Quando você interpola do amarelo para o azul em HSL, o brilho percebido oscila e cai de maneiras que parecem incoerentes.
/* Gradiente HSL — o brilho perceptual é desigual entre as matizes */
background: linear-gradient(in hsl, hsl(60 100% 50%), hsl(240 100% 50%));
O ponto intermediário deste gradiente em hsl(150, 100%, 50%) é um verde vívido que parece perceptualmente mais brilhante do que qualquer um dos extremos. O gradiente atinge seu pico no meio em vez de fazer a transição suavemente.
A interpolação HSL também tem um problema de arco longo: o ângulo de matiz envolve em 360°, e se você interpolar de hsl(350, ...) (próximo ao vermelho) para hsl(20, ...) (laranja), o HSL pode percorrer o longo caminho ao redor do círculo de matiz por azul, verde e amarelo em vez do caminho curto pelo vermelho.
OKLCH: Consistência e Uniformidade Perceptual
O OKLCH é uma forma cilíndrica do espaço de cores Oklab, projetado por Björn Ottosson em 2020 especificamente para resolver as deficiências de uniformidade perceptual dos espaços de cores anteriores. Seus três canais — L (luminosidade), C (croma) e H (ângulo de matiz) — são calibrados para que mudanças numéricas iguais em L produzam mudanças iguais no brilho percebido, independentemente da matiz.
Quando você interpola entre duas cores OKLCH, obtém:
- Brilho percebido consistente ao longo da transição — sem mergulhar em pontos intermediários escuros ou picos de brilho súbitos.
- Croma preservado — os pontos intermediários permanecem vívidos porque o croma é interpolado independentemente da matiz.
- Caminhos de matiz mais curtos e intuitivos — os ângulos de matiz do OKLCH são distribuídos em ordem perceptual, então a interpolação percorre as matizes intermediárias esperadas.
/* Gradiente OKLCH — vívido, perceptualmente uniforme */
background: linear-gradient(in oklch, red, blue);
Um gradiente do vermelho ao azul em OKLCH percorre magenta e roxo vívidos — os pontos intermediários perceptualmente intuitivos. Permanece saturado e uniformemente brilhante ao longo de todo o percurso.
Comparação Lado a Lado
| Gradiente | Cor do Ponto Intermediário | Qualidade Percebida |
|---|---|---|
in srgb do vermelho ao verde |
#808000 — azeitona opaco | Vale escuro e opaco |
in hsl do amarelo ao azul |
Pico de verde vívido | Brilho desigual, pico de cor |
in oklch do vermelho ao verde |
Amarelo quente vívido | Suave, saturado, uniforme |
Para ver a diferença você mesmo, use o Gerador de Gradientes que permite visualizar gradientes em diferentes espaços de cores.
Como Converter Suas Cores para OKLCH
Você não precisa reescrever cada valor de cor no seu CSS. O sinalizador in oklch em um gradiente instrui o navegador a converter as cores dos extremos para OKLCH antes de interpolar, depois converter de volta ao espaço de cores de saída. Você pode manter seus valores HEX:
/* Esses extremos HEX são automaticamente convertidos para OKLCH na interpolação */
background: linear-gradient(in oklch, #FF5733, #3498DB);
#FF5733 é aproximadamente oklch(0.63 0.24 27) e #3498DB é aproximadamente oklch(0.63 0.14 232). Use o Conversor de Cores para verificar os valores OKLCH de qualquer código HEX antes de projetar um gradiente, para saber com antecedência o que a interpolação percorrerá.
A Função color-mix()
A função CSS color-mix() é a API declarativa para misturar duas cores, disponível em todos os navegadores modernos desde 2023. Sua sintaxe inclui o espaço de cores de interpolação como primeiro argumento:
color: color-mix(in oklch, #FF5733 50%, #3498DB);
Isso mistura #FF5733 e #3498DB em proporções iguais no espaço OKLCH. O resultado é um intermediário vívido que parece um ponto perceptual real entre as duas cores — não uma média sRGB opaca.
Usos Práticos de color-mix()
Criando variantes transparentes:
:root {
--brand: #2563EB;
--brand-10: color-mix(in oklch, var(--brand) 10%, transparent);
--brand-20: color-mix(in oklch, var(--brand) 20%, transparent);
--brand-50: color-mix(in oklch, var(--brand) 50%, transparent);
}
Tingindo em direção ao branco ou preto:
:root {
--brand: #2563EB;
--brand-light: color-mix(in oklch, var(--brand) 70%, white);
--brand-dark: color-mix(in oklch, var(--brand) 70%, black);
}
Essa é a mesma ideia de um gerador de matizes, mas completamente em CSS, sem pré-processamento. O resultado na tingimento OKLCH parece mais natural do que operações equivalentes em HSL porque o croma se desloca apropriadamente ao se aproximar do branco ou do preto.
Derivação de estado hover:
.button {
background: var(--brand);
}
.button:hover {
background: color-mix(in oklch, var(--brand) 80%, black);
}
Aviso: color-mix() em sRGB
Se você omitir o argumento in <colorspace>, color-mix() usa interpolação sRGB por padrão:
/* Isso usa sRGB — pode produzir resultados opacos */
color: color-mix(#FF5733, #3498DB);
/* Correto: especifique o espaço */
color: color-mix(in oklch, #FF5733, #3498DB);
Sempre especifique in oklch (ou outro espaço preferido) explicitamente. O padrão sRGB é preservado para compatibilidade retroativa, mas raramente é a melhor escolha.
Espaço de Cores de Interpolação de Gradiente
A sintaxe moderna do CSS permite especificar o espaço de cores de interpolação diretamente em uma declaração de gradiente usando in <colorspace> após a palavra-chave de direção:
/* sRGB (padrão, frequentemente opaco) */
background: linear-gradient(to right, red, blue);
/* sRGB linear (melhor luminância, ainda tem problemas de matiz) */
background: linear-gradient(in srgb-linear to right, red, blue);
/* HSL (mudanças de matiz, brilho desigual) */
background: linear-gradient(in hsl to right, red, blue);
/* OKLCH (recomendado: vívido, perceptualmente uniforme) */
background: linear-gradient(in oklch to right, red, blue);
/* Oklab (também excelente, sintaxe menos intuitiva) */
background: linear-gradient(in oklab to right, red, blue);
Esta sintaxe aplica-se a todos os tipos de gradiente: linear-gradient, radial-gradient e conic-gradient.
Direção de Interpolação de Matiz no OKLCH
Para interpolação de matiz especificamente, você pode controlar se o gradiente toma o arco mais curto ou mais longo ao redor do círculo de matiz:
/* Arco mais curto (padrão) */
background: linear-gradient(in oklch, hsl(30 100% 50%), hsl(270 100% 50%));
/* Arco mais longo — percorre amarelo, verde, ciano, depois roxo */
background: linear-gradient(in oklch longer hue, hsl(30 100% 50%), hsl(270 100% 50%));
/* Arco crescente — sempre vai na direção do ângulo de matiz crescente */
background: linear-gradient(in oklch increasing hue, hsl(30 100% 50%), hsl(270 100% 50%));
A palavra-chave shorter hue (padrão) fornece o resultado mais natural na maioria dos casos. A variante longer hue é útil para efeitos arco-íris ou quando você especificamente quer que o gradiente percorra uma ampla parte do espectro de matiz.
Gradientes com Múltiplas Paradas
A interpolação OKLCH se torna ainda mais valiosa para gradientes com múltiplas paradas, porque cada segmento interpola por pontos intermediários perceptualmente vívidos:
/* Um gradiente arco-íris que permanece vívido ao longo de todo o percurso */
background: linear-gradient(
in oklch to right,
oklch(0.70 0.20 30), /* laranja-vermelho */
oklch(0.80 0.20 90), /* amarelo */
oklch(0.75 0.20 150), /* verde */
oklch(0.65 0.20 240), /* azul */
oklch(0.60 0.20 300) /* roxo */
);
Como os valores de L e C são perceptualmente calibrados, definir valores similares em todas as paradas resulta em um arco-íris que parece naturalmente brilhante e saturado, sem as quedas de luminância comuns em arco-íris sRGB.
Suporte de Navegadores
A sintaxe in <colorspace> de gradiente é suportada em todos os principais navegadores:
- Chrome/Edge: Suporte completo desde a versão 111 (março de 2023)
- Firefox: Suporte completo desde a versão 113 (maio de 2023)
- Safari: Suporte completo desde a versão 16.2 (dezembro de 2022)
Para navegadores mais antigos, use graciosamente a sintaxe legada primeiro:
/* Fallback: gradiente sRGB */
background: linear-gradient(to right, #FF5733, #3498DB);
/* Moderno: interpolação OKLCH */
@supports (background: linear-gradient(in oklch, red, blue)) {
background: linear-gradient(in oklch to right, #FF5733, #3498DB);
}
Principais Conclusões
- A interpolação sRGB (o padrão CSS) produz pontos intermediários opacos e dessaturados quando gradientes passam perto do centro do cubo sRGB — particularmente visível em gradientes vermelho-verde e de cores complementares.
- A interpolação HSL evita alguns problemas do RGB, mas introduz brilho percebido inconsistente — seu canal de Luminosidade não é perceptualmente uniforme — e pode produzir caminhos de matiz inesperados.
- A interpolação OKLCH produz pontos intermediários vívidos e perceptualmente consistentes porque foi projetada em torno da visão humana. Os gradientes em OKLCH permanecem saturados e uniformemente brilhantes em todo o seu intervalo.
- Use
in oklchem qualquer gradiente:linear-gradient(in oklch to right, red, blue). Usecolor-mix(in oklch, color1 50%, color2)para mistura programática. - O Conversor de Cores permite converter valores HEX ou RGB para OKLCH para que você possa entender como suas cores irão interpolar antes de se comprometer com um design de gradiente.
- O Gerador de Gradientes permite visualizar como diferentes espaços de cores afetam a saída do gradiente para qualquer par de cores.
- A direção de interpolação de matiz pode ser controlada com as palavras-chave
shorter hue,longer hue,increasing hueedecreasing hue— úteis para efeitos arco-íris e controle preciso de gradiente com múltiplas paradas.