Tutoriais

Sintaxe de Cor Relativa CSS: Transforme Qualquer Cor Dinamicamente

9 min de leitura

O CSS há muito tempo consegue armazenar cores, mas manipulá-las exigia JavaScript, funções Sass ou uma etapa de build. A sintaxe de cor relativa CSS muda isso. Ela permite pegar uma cor existente — de uma variável, uma palavra-chave ou qualquer valor de cor — e transformar canais específicos dela diretamente na sua folha de estilos. Você pode clareá-la, deslocar seu matiz, reduzir seu croma ou ajustar sua transparência, tudo em CSS puro, em tempo de execução.

Esse recurso chegou no Chrome 119, Firefox 128 e Safari 16.4, colocando-o em penetração de navegadores alta o suficiente para uso em produção em 2026. Funciona com todas as funções de cor CSS modernas: rgb(), hsl(), oklch(), lab(), lch() e mais.

O que é Sintaxe de Cor Relativa?

A sintaxe de cor relativa estende qualquer função de cor CSS com uma cláusula from <color> no início. Isso diz ao navegador para decompor a cor de origem em seus canais, então recompor uma nova cor usando esses canais — possivelmente com modificações.

O exemplo mais básico usa a palavra-chave from para passar uma cor sem alterações:

/* Isto é uma operação nula — produz a mesma cor que a entrada */
color: oklch(from #3B82F6 l c h);

Não é muito útil por si só, mas o poder real vem quando você modifica os valores de canal extraídos:

/* Clarear aumentando L (luminosidade) */
color: oklch(from #3B82F6 calc(l + 0.15) c h);

/* Deslocar matiz em 30 graus */
color: oklch(from #3B82F6 l c calc(h + 30));

/* Dessaturar reduzindo o croma */
color: oklch(from #3B82F6 l calc(c * 0.5) h);

/* Tornar semitransparente */
color: oklch(from #3B82F6 l c h / 0.5);

Cada uma dessas transformações modifica um único canal mantendo os outros intactos — algo que anteriormente era impossível em CSS puro sem um pré-processador.

A Palavra-chave from

A palavra-chave from é o coração sintático da sintaxe de cor relativa. Ela aparece imediatamente após o parêntese de abertura da função de cor e antes dos valores de canal:

color-function(from <origin-color> <channel1> <channel2> <channel3> [/ <alpha>])

O <origin-color> pode ser qualquer valor de cor CSS válido:

/* De um código hex */
oklch(from #FF5733 l c h)

/* De uma cor nomeada */
oklch(from tomato l c h)

/* De uma propriedade personalizada CSS */
oklch(from var(--brand-color) l c h)

/* De outra função de cor */
oklch(from rgb(59, 130, 246) l c h)

/* De currentColor */
oklch(from currentColor l c h)

A variante from currentColor é particularmente poderosa — ela permite que um componente transforme a cor de texto herdada sem conhecer seu valor exato.

Nomes de Canais por Função de Cor

Cada função de cor expõe seus canais com nomes específicos após a palavra-chave from:

Função Canal 1 Canal 2 Canal 3 Alfa
oklch() l c h alpha
oklab() l a b alpha
hsl() h s l alpha
rgb() r g b alpha
lab() l a b alpha
lch() l c h alpha

Note que em hsl(), a ordem dos canais na decomposição from reflete a assinatura da função: h, s, l. Em oklch(), é l, c, h. Sempre verifique a ordem dos canais para a função que você está usando.

Conversão Entre Funções

A cor de origem não precisa corresponder à função de saída. O navegador converte automaticamente:

/* A entrada é hex, a saída é oklch — o navegador converte primeiro, depois decompõe */
oklch(from #FF5733 calc(l + 0.1) c h)

/* A entrada é hsl, a saída é rgb */
rgb(from hsl(200, 80%, 50%) calc(r * 0.9) g b)

Essa conversão entre funções significa que você pode armazenar seus tokens de design em qualquer formato e produzir saídas em qualquer formato que preferir para manipulação.

Ajustando Canais Individualmente

As operações mais comuns em cores relativas envolvem calc() para modificar valores de canal extraídos.

Ajustes de Luminosidade (OKLCH)

Com OKLCH, o canal l varia de 0 (preto) a 1 (branco). Adicionar ou subtrair um valor fixo produz um resultado previsivelmente mais claro ou mais escuro, porque a luminosidade OKLCH é perceptualmente uniforme:

:root {
  --base: oklch(0.58 0.20 250);
}

.lighter  { color: oklch(from var(--base) calc(l + 0.15) c h); }
.lightest { color: oklch(from var(--base) calc(l + 0.30) c h); }
.darker   { color: oklch(from var(--base) calc(l - 0.15) c h); }
.darkest  { color: oklch(from var(--base) calc(l - 0.30) c h); }

Como a luminosidade OKLCH é calibrada perceptualmente, adicionar 0,15 a l produz um salto de brilho percebido de tamanho igual independentemente do matiz da cor — ao contrário do HSL, onde o mesmo incremento parece diferente dependendo se a cor é amarela ou azul.

Ajustes de Croma

O canal c controla a intensidade da cor. Defini-lo como 0 produz um cinza neutro na mesma luminosidade. Reduzi-lo dessatura sem ficar completamente cinza:

/* Variante suavizada — 50% menos croma */
color: oklch(from var(--brand) l calc(c * 0.5) h);

/* Cinza totalmente dessaturado na mesma luminosidade */
color: oklch(from var(--brand) l 0 h);

/* Mais vívido — 30% mais croma (pode sair da gama sRGB em alguns matizes) */
color: oklch(from var(--brand) l calc(c * 1.3) h);

Deslocamentos de Matiz

O canal h é um valor de graus de 0 a 360. Adicionar ou subtrair desloca o matiz ao redor da roda de cores:

/* Cor complementar — lado oposto da roda */
color: oklch(from var(--brand) l c calc(h + 180));

/* Análogo +30° */
color: oklch(from var(--brand) l c calc(h + 30));

/* Análogo -30° */
color: oklch(from var(--brand) l c calc(h - 30));

Combinar múltiplos ajustes de canal cria transformações complexas em uma única declaração:

/* Mais claro, mais suave e com matiz ligeiramente diferente — uma variante tonal */
color: oklch(from var(--brand) calc(l + 0.12) calc(c * 0.6) calc(h + 15));

Canal Alfa

Use a sintaxe de barra para modificar a transparência:

/* Versão com 50% de opacidade da cor da marca */
background: oklch(from var(--brand) l c h / 0.5);

/* Versão totalmente opaca de uma cor que pode ter transparência */
color: oklch(from var(--text-muted) l c h / 1);

/* Escalar alfa existente — se a origem tem 0.8 de opacidade, reduzir para ~0.4 */
background: oklch(from var(--overlay) l c h / calc(alpha * 0.5));

Criando Tintes e Sombras em CSS Puro

A abordagem tradicional para escalas de cores exige pré-calcular cada sombra e armazená-la como uma variável. Com a sintaxe de cor relativa, você pode gerar uma escala inteira a partir de uma única variável base:

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

  /* Escala — sem pré-computação necessária */
  --primary-50:  oklch(from var(--primary) 0.97 calc(c * 0.1) h);
  --primary-100: oklch(from var(--primary) 0.94 calc(c * 0.2) h);
  --primary-200: oklch(from var(--primary) 0.88 calc(c * 0.4) h);
  --primary-300: oklch(from var(--primary) 0.78 calc(c * 0.6) h);
  --primary-400: oklch(from var(--primary) 0.68 calc(c * 0.8) h);
  --primary-500: var(--primary);
  --primary-600: oklch(from var(--primary) calc(l - 0.08) c h);
  --primary-700: oklch(from var(--primary) calc(l - 0.16) c h);
  --primary-800: oklch(from var(--primary) calc(l - 0.24) c h);
  --primary-900: oklch(from var(--primary) calc(l - 0.32) c h);
  --primary-950: oklch(from var(--primary) calc(l - 0.38) c h);
}

Mude --primary para qualquer cor e toda a escala de 11 passos é regenerada automaticamente no navegador. Sem etapa de build, sem JavaScript, sem Sass.

Para sistemas de design de produção que requerem passos perceptuais muito precisos, o Gerador de Sombras fornece escalas de 50 a 950 ajustadas manualmente. A abordagem de cor relativa é ideal para componentes de menor escala ou para prototipagem rápida onde a precisão exata importa menos do que a flexibilidade.

Tintes Acessíveis para Fundos

Um padrão comum é criar fundos com tinte muito claro para banners de notificação e caixas de alerta:

:root {
  --success: oklch(0.65 0.20 145);  /* Um verde vívido */
  --warning: oklch(0.75 0.18 70);   /* Um âmbar quente */
  --danger:  oklch(0.62 0.24 25);   /* Um vermelho forte */
}

.alert-success {
  background: oklch(from var(--success) 0.96 0.04 h);
  border-left: 3px solid var(--success);
  color: oklch(from var(--success) 0.30 0.14 h);
}

.alert-warning {
  background: oklch(from var(--warning) 0.97 0.04 h);
  border-left: 3px solid var(--warning);
  color: oklch(from var(--warning) 0.35 0.14 h);
}

.alert-danger {
  background: oklch(from var(--danger) 0.96 0.04 h);
  border-left: 3px solid var(--danger);
  color: oklch(from var(--danger) 0.32 0.14 h);
}

O fundo é uma versão de luminosidade muito alta e baixo croma da cor do alerta. O texto usa uma versão muito escura e moderadamente saturada. O matiz (h) é preservado da cor de origem em todos os casos — tudo permanece no mesmo matiz automaticamente.

Exemplos do Mundo Real com OKLCH

Estados Hover Adaptativos ao Tema

.card {
  --card-accent: oklch(0.60 0.18 260);
  background: var(--card-accent);
  transition: background-color 150ms ease;
}

.card:hover {
  /* Escurecer levemente no hover — funciona independentemente do que o acento seja */
  background: oklch(from var(--card-accent) calc(l - 0.06) c h);
}

Esse padrão é particularmente poderoso em bibliotecas de componentes onde a cor de acento é passada como prop ou propriedade personalizada. O estado de hover é sempre contextualmente apropriado sem exigir cores de hover separadas para cada variante.

Texto sobre Fundos Coloridos

.chip {
  --chip-color: oklch(0.62 0.20 260);

  /* Fundo: tinte muito claro */
  background: oklch(from var(--chip-color) 0.94 0.06 h);

  /* Texto: versão muito escura do mesmo matiz */
  color: oklch(from var(--chip-color) 0.28 0.16 h);

  /* Borda: versão médio-clara */
  border: 1px solid oklch(from var(--chip-color) 0.78 0.12 h);
}

Isso produz um chip colorido onde fundo, texto e borda são todos harmoniosos porque compartilham o mesmo matiz. Mude --chip-color e todo o conjunto é atualizado.

Adaptação ao Modo Escuro Usando from currentColor

.icon-wrapper {
  /* A cor do ícone herda do contexto de texto */
  color: var(--color-text-primary);
}

.icon-wrapper:hover {
  /* Versão sutilmente mais escura de qualquer cor que o ícone atualmente seja */
  color: oklch(from currentColor calc(l - 0.08) c h);
}

.icon-wrapper .background-glow {
  /* Versão semitransparente da cor do ícone, para um efeito de brilho */
  background: oklch(from currentColor l c h / 0.15);
}

A origem currentColor significa que este componente funciona corretamente em qualquer contexto de cor de texto, incluindo modo escuro, sem precisar conhecer o valor específico da cor.

Gerando um Acento Complementar

Para designs que precisam de uma cor de acento complementar derivada da cor primária da marca:

:root {
  --brand: oklch(0.60 0.20 250);   /* Azul */

  /* Complemento: matiz oposto, mesma luminosidade e croma */
  --accent: oklch(from var(--brand) l c calc(h + 180));
  /* Resultado: aproximadamente laranja no matiz ~70° */

  /* Complemento mais suave para fundos */
  --accent-bg: oklch(from var(--brand) 0.95 0.06 calc(h + 180));
}

Isso produz uma cor matematicamente complementar. Para um esquema split-complementar mais sofisticado, desloque por ±150° ou ±160° em vez de 180°.

Suporte de Navegadores e Fallbacks

A sintaxe de cor relativa é suportada em:

  • Chrome/Edge: desde a versão 119 (novembro de 2023)
  • Firefox: desde a versão 128 (julho de 2024)
  • Safari: desde a versão 16.4 (março de 2023) — Safari foi o primeiro

O suporte global é de cerca de 85-88% no início de 2026. Para cobertura mais ampla, forneça fallbacks:

.btn-hover {
  /* Fallback: hex pré-computado para navegadores mais antigos */
  background-color: #1D4ED8;
}

@supports (color: oklch(from red l c h)) {
  .btn-hover {
    /* Moderno: derivado dinamicamente da base */
    background-color: oklch(from var(--btn-bg) calc(l - 0.08) c h);
  }
}

O teste @supports (color: oklch(from red l c h)) verifica especificamente o suporte à sintaxe de cor relativa, não apenas o suporte ao OKLCH, o que é importante porque OKLCH e sintaxe de cor relativa chegaram em versões de navegador diferentes.

Principais Conclusões

  • A sintaxe de cor relativa usa from <origin-color> dentro de qualquer função de cor CSS para decompor essa cor em seus canais, que podem então ser modificados com calc() e recompostos em uma nova cor.
  • O OKLCH é a melhor função para usar na manipulação de cor relativa porque seus canais (luminosidade, croma, matiz) se mapeiam de perto para a intenção de design, e a luminosidade é perceptualmente uniforme — incrementos iguais produzem mudanças de aparência iguais.
  • Você pode ajustar qualquer canal individual de forma independente: somar a l para clarear, multiplicar c para dessaturar, somar a h para deslocar o matiz ou modificar alpha para mudar a transparência.
  • A origem from currentColor cria componentes autoadaptativos que derivam suas cores da cor de texto herdada, tornando-os automaticamente corretos em qualquer contexto, incluindo modo escuro.
  • O suporte de navegadores cobre todos os navegadores modernos desde o final de 2023 / meados de 2024. Use @supports (color: oklch(from red l c h)) para detectar suporte especificamente para a sintaxe de cor relativa.
  • Use o Gerador de Sombras para escalas de 50 a 950 precisas e ajustadas manualmente em sistemas de design de produção. Use a sintaxe de cor relativa para variantes dinâmicas e derivadas em tempo de execução em componentes.
  • Use o Conversor de Cores para traduzir suas cores hex de marca existentes para valores OKLCH para entender seus canais l, c e h antes de escrever expressões de cor relativa.

Cores relacionadas

Marcas relacionadas

Ferramentas relacionadas