Substituindo funções de cor do Sass por CSS nativo
12 anos atrás, no artigo Colour me Sass-y, Stuart Robson apresentou uma série de helpers de cor do Sass que tornavam a estilização diária rápida e prática.
Naquela época, o Sass era o caminho mais fácil. Em 2026, o CSS moderno oferece muito mais poder nativo de manipulação de cores do que havia em 2014.
tl;dr
Se o fluxo de trabalho com Sass depende muito de helpers de cor, estas são as principais substituições nativas em CSS:
rgba($color, 0.4)→rgb(from var(--color) r g b / 40%)lighten($color, 20%)→hsl(from var(--color) h s calc(l + 20))(paridade com Sass)darken($color, 20%)→hsl(from var(--color) h s calc(l - 20))(paridade com Sass)tint($color, 20%)→color-mix(in srgb, var(--color) 80%, white 20%)(paridade com Sass)shade($color, 20%)→color-mix(in srgb, var(--color) 80%, black 20%)(paridade com Sass)adjust-hue($color, 40deg)→hsl(from var(--color) calc(h + 40) s l)grayscale($color)→hsl(from var(--color) h 0% l)complement($color)→hsl(from var(--color) calc(h + 180) s l)
lighten()/darken() e tint()/shade() não são a mesma operação no Sass. lighten()/darken() ajustam a luminosidade HSL, enquanto tint()/shade() fazem mistura com branco/preto.
Substituições adicionais:
saturate($color, 20%)→hsl(from var(--color) h calc(s + 20) l)desaturate($color, 20%)→hsl(from var(--color) h calc(s - 20) l)
Por que isso funciona melhor agora
O Sass trouxe manipulação de cores muito antes dos navegadores; agora o CSS nativo alcançou esse patamar de duas formas importantes:
color-mix()oferece mistura confiável para tints, shades e blending.- A sintaxe de cores relativas (
rgb(from ...),hsl(from ...)) permite derivar novas cores a partir de tokens existentes.
Juntas, essas funcionalidades abrem um fluxo de trabalho onde uma única cor de origem pode gerar múltiplos estados e temas.
Uma cor de origem
A ideia é manter uma cor principal da marca como custom property CSS e derivar tudo a partir dela.
Uma boa regra geral: usar OKLCH para os tokens e OKLab para as misturas. OKLCH — lightness, chroma, hue — é fácil de ler e ajustar manualmente. OKLab mistura de forma mais limpa, sem mudanças inesperadas de matiz no meio do caminho.
:root { --brand: oklch(62% 0.19 26);
/* Superfícies e ênfase */ --brand-soft: color-mix(in oklab, var(--brand), white 88%); --brand-strong: color-mix(in oklab, var(--brand), black 22%);
/* Estados */ --brand-hover: color-mix(in oklab, var(--brand), black 12%); --brand-active: color-mix(in oklab, var(--brand), black 24%); --brand-border: color-mix(in oklab, var(--brand), black 35%);
/* Variantes com alfa */ --brand-alpha-08: rgb(from var(--brand) r g b / 8%); --brand-alpha-18: rgb(from var(--brand) r g b / 18%);}Com essa abordagem, não se está mais armazenando dez valores hex sem relação entre si. Os valores são derivados de uma única custom property, o que torna refatoração e tematização muito mais fáceis. Inclusive, esse é o tipo de técnica que pode ser aproveitada para criar dark mode com CSS de forma muito mais simples.
Substituindo funções comuns de cor do Sass
rgba()
A versão clássica do Sass:
$brand: #d13400;background-color: rgba($brand, 20%);Equivalente em CSS nativo:
:root { --brand: #d13400;}
.alert { background-color: rgb(from var(--brand) r g b / 20%);}lighten() e darken()
Ambas são nativas do Sass e ajustam a luminosidade HSL diretamente:
lighten(#6b717f, 20%);darken(#6b717f, 20%);Equivalente em CSS nativo usando sintaxe de cores relativas:
:root { --brand: #6b717f;
--brand-lighten-20: hsl(from var(--brand) h s calc(l + 20)); --brand-darken-20: hsl(from var(--brand) h s calc(l - 20));}Para resultados com aparência mais natural, pode-se usar OKLCH:
:root { --brand: #6b717f;
--brand-lighten-20: oklch(from var(--brand) calc(l + 0.2) c h); --brand-darken-20: oklch(from var(--brand) calc(l - 0.2) c h);}tint() e shade()
Estas não eram nativas do Sass, eram comumente escritas como helpers personalizados ou obtidas de uma biblioteca:
@function tint($color, $percentage) { @return mix(white, $color, $percentage);}
@function shade($color, $percentage) { @return mix(black, $color, $percentage);}Equivalente em CSS nativo usando color-mix(). Pode-se usar srgb para paridade com o Sass, ou trocar para oklab para misturas com melhor aparência perceptual:
:root { --brand: #6b717f;
/* srgb: mais próximo da saída do Sass */ --brand-tint-20: color-mix(in srgb, var(--brand) 80%, white 20%); --brand-shade-20: color-mix(in srgb, var(--brand) 80%, black 20%);
/* oklab: melhor mistura perceptual */ --brand-tint-20: color-mix(in oklab, var(--brand) 80%, white 20%); --brand-shade-20: color-mix(in oklab, var(--brand) 80%, black 20%);}adjust-hue() e complement()
As versões do Sass:
adjust-hue(#d13400, 40deg);complement(#d13400);Equivalente em CSS nativo usando sintaxe de cores relativas em hsl():
:root { --brand: #d13400;
--brand-shift-40: hsl(from var(--brand) calc(h + 40) s l); --brand-complement: hsl(from var(--brand) calc(h + 180) s l);}Demonstração de adjust-hue():
Demonstração de complement():
grayscale()
A versão do Sass:
grayscale(#d13400);Equivalente em CSS nativo:
:root { --brand: #d13400; --brand-gray: hsl(from var(--brand) h 0% l);}saturate() e desaturate()
As versões do Sass:
saturate(#d13400, 20%);desaturate(#d13400, 20%);Equivalente em CSS nativo:
:root { --brand: #d13400;
--brand-more-sat: hsl(from var(--brand) h calc(s + 20) l); --brand-less-sat: hsl(from var(--brand) h calc(s - 20) l);}Um exemplo prático de componente
Aqui está uma receita simples de botão que obtém todos os seus estados de cor a partir de um único token.
:root { --btn: oklch(58% 0.2 28); --btn-text: white;
--btn-hover: color-mix(in oklab, var(--btn), black 10%); --btn-active: color-mix(in oklab, var(--btn), black 18%); --btn-ring: rgb(from var(--btn) r g b / 35%); --btn-subtle-bg: color-mix(in oklab, var(--btn), white 90%);}
.button { background: var(--btn); color: var(--btn-text); border: 1px solid color-mix(in oklab, var(--btn), black 30%); box-shadow: 0 0 0 0 var(--btn-ring);}
.button:hover { background: var(--btn-hover);}
.button:active { background: var(--btn-active);}
.button:focus-visible { box-shadow: 0 0 0 0.25rem var(--btn-ring);}
.button--subtle { background: var(--btn-subtle-bg); color: color-mix(in oklab, var(--btn), black 45%);}Esse é um conjunto completo de estados a partir de uma única cor de origem, sem necessidade de funções Sass.
Progressive enhancement e fallbacks
As funções de cor modernas têm excelente suporte nos navegadores, mas se for necessário dar suporte a navegadores mais antigos, será preciso usar fallbacks. A estratégia é direta: fornecer uma cor estática primeiro, depois aprimorar com @supports.
Fallback básico com @supports
.badge { /* Fallback: cor estática que funciona em qualquer lugar */ background: #d13400; color: white;}
@supports (color: color-mix(in oklab, red, white)) { /* Aprimoramento: cores derivadas para navegadores modernos */ .badge { background: color-mix(in oklab, #d13400, white 15%); color: color-mix(in oklab, #d13400, black 55%); }}Suporte dos navegadores
color-mix: color-mix() permite misturar duas cores com um peso especificado, sendo essencial para criar tints, shades e variações de cor personalizadas sem Sass.
Sintaxe de cores relativas: a sintaxe de cores relativas permite derivar novas cores a partir de existentes usando funções como hsl(from var(--color) ...), possibilitando transformações de cor dinâmicas diretamente no CSS.
Conclusão
O Sass ainda é uma ferramenta válida e ainda é utilizado por muitos. Mas, especificamente para trabalho com cores, o CSS nativo passou de “quase lá” para “muito utilizável”.
Se o projeto pode contar com suporte a navegadores modernos, já é possível fazer bastante manipulação de cores diretamente em CSS. Ou seja, dá para “des-Sassificar” o CSS um pouco mais.
Para quem quer se aprofundar, vale conferir também o artigo sobre o que é possível colocar em uma variável CSS e a discussão sobre se variáveis CSS são melhores que loops de Sass.