Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIntermediáriocódigo testado

Funções e operações no Sass: math.div, cores e @function

Por que 16px / 2 não vira 8px no Dart Sass atual, como usar math.div e color.adjust, e como escrever a sua própria função.

Rodolfo Mori4 min de leitura

Sass calcula valores durante o build. Ele conhece números, unidades, cores, listas e maps, e permite criar funções com contrato próprio. A sintaxe moderna coloca APIs nativas em módulos como sass:math e sass:color; copiar chamadas globais de tutorial antigo gera avisos e prepara uma quebra futura.

Registrei as versões antes de compilar:

bash
node --version
npx --yes sass@1.103.1 --version
v26.3.0 1.103.1 compiled with dart2js 3.13.1

Cada trecho SCSS abaixo foi enviado à entrada padrão com o mesmo comando:

bash
npx --yes sass@1.103.1 --stdin --no-source-map --style=expanded

A barra já não significa divisão automaticamente

CSS usa / em valores como font, grid e cores modernas. Para preservar essa sintaxe, Sass atual não trata toda barra como operação. Este código mantém a expressão na saída:

css
.demo { width: 16px / 2; }
.demo { width: 16px/2; }

Isso não é oito pixels calculados pelo Sass. Dependendo da propriedade, pode ser um valor CSS inválido ou uma expressão com outro significado. A intenção de dividir precisa estar explícita.

math.div: divisão conhecida no build

Carregue o módulo e passe numerador e denominador:

css
@use "sass:math";
.demo { width: math.div(16px, 2); }
.demo { width: 8px; }

O namespace diz de onde vem a função e evita colisão com nomes do projeto. Uma divisão por número sem unidade preserva px; dividir dois valores de mesma dimensão pode cancelar a unidade.

Unidades não são texto decorativo

Sass acompanha dimensões. Quando não consegue simplificar para um valor fixo, ele pode preservar uma expressão CSS. Dividir 1rem por 16px produziu:

css
@use "sass:math";
.demo { width: math.div(1rem, 16px); }
.demo { width: calc(0.0625rem / 1px); }

Essa saída ainda mistura unidades e provavelmente não é o que um token de tamanho queria. Defina o contrato da função: para converter pixels em rem, a entrada base também deve estar em pixels para as unidades se cancelarem.

Cor moderna com sass:color

As funções globais darken() e lighten() estão depreciadas. A alternativa explícita carrega o módulo e nomeia o canal ajustado:

css
@use "sass:color";
.button {
  background: color.adjust(#6d28d9, $lightness: -10%);
}
.button { background: rgb(34.1656978997%, 12.1336123382%, 68.6507013873%); }

O formato numérico longo é saída real do espaço de cor usado pelo compilador. Não troque pelo hex que “parece igual” sem medir. Se a cor precisa reagir a uma custom property no navegador, prefira color-mix() do CSS; Sass só conhece cores resolvidas no build.

Escrever @function: pixels para rem

Função recebe argumentos e devolve um valor com @return. Não deve emitir uma regra inteira; esse papel pertence ao mixin.

css
@use "sass:math";

@function rem($px, $base: 16px) {
  @return math.div($px, $base) * 1rem;
}

.title { font-size: rem(24px); }
.title { font-size: 1.5rem; }

As unidades px/px se cancelam, restando um número multiplicado por 1rem. O parâmetro $base aceita configuração quando o projeto usa outra referência, mas o padrão fica documentado na assinatura.

Falhar cedo com @error

Uma função pode validar sua entrada. Ao receber 2rem onde o contrato exige pixels, ela encerra a compilação com mensagem própria:

css
@use "sass:math";

@function rem($px, $base: 16px) {
  @if math.unit($px) != "px" {
    @error "$px precisa estar em px";
  }
  @return math.div($px, $base) * 1rem;
}

.title { font-size: rem(2rem); }
Error: "$px precisa estar em px" ╷ 10 │ .title { font-size: rem(2rem); } │ ^^^^^^^^^ ╵ - 10:21 root stylesheet

O número e a coluna acima pertencem exatamente ao bloco formatado desta página. Um erro claro no build é melhor que uma unidade silenciosamente incorreta.

Limites e arredondamento

sass:math oferece funções para limitar, arredondar, encontrar mínimo e máximo. No exemplo, sete é limitado a quatro e 24px é dividido por três:

css
@use "sass:math";
.grid {
  columns: math.clamp(1, 7, 4);
  gap: math.div(24px, 3);
}
.grid { columns: 4; gap: 8px; }

Não confunda math.clamp(), resolvido no build, com clamp() do CSS, que pode combinar viewport, rem e custom properties no navegador. O nome parecido não iguala o momento da decisão.

Função ou mixin?

A divisão é simples: função retorna valor; mixin emite bloco. Se a chamada cabe depois de font-size:, ela é função. Se a chamada precisa inserir padding, border e media query, use mixin.

Função personalizada deve trabalhar com uma unidade clara. Se aceita pixels, valide pixels; se aceita número sem unidade, não adicione rem escondido sem documentar. Operações entre medidas compatíveis podem ser convertidas pelo Sass, mas misturar tempo de build com expressão do navegador frequentemente produz um calc() que não atende ao contrato pretendido.

Escolha nomes pelo resultado: rem(), contrast-color() ou space() explicam o valor entregue. Nomes como calculate() e transform() apenas repetem que há trabalho. Evite efeitos colaterais e variáveis globais; a mesma entrada deve produzir a mesma saída para que testes e cache façam sentido.

Ao criar uma escala, compare uma função Sass com custom properties e variáveis de build. Se o valor responde ao tamanho do container, tema ou preferência do usuário, preserve cálculo CSS. Se ele valida tokens conhecidos e gera pacote estático, resolva no Sass. O local de execução é parte do design da API.

Depreciações merecem teste dedicado. Execute o compilador sem silenciar warnings, registre a versão e migre funções globais para seus namespaces. A saída visual pode permanecer igual enquanto a manutenção melhora; compare valores exatos, especialmente cores, porque diferentes espaços e estratégias de ajuste não são intercambiáveis.

text
rem(24px) → 1.5rem
@include button(...) → várias declarações CSS

O contraste acima é conceitual: uma função compõe valores; um mixin compõe estrutura. Mantenha funções curtas, puras e nomeadas pelo resultado. Para entender onde os módulos sass:math e sass:color entram na arquitetura, consulte o guia de Sass. A próxima lição troca APIs globais por módulos próprios com @use e @forward.

Antes de publicar uma função, teste zero, limite inferior, limite superior, unidade errada e valor negativo. Um exemplo feliz prova pouco; o erro reproduzido mostra que o contrato protege o consumidor. Se a mensagem aponta a chamada e explica a unidade esperada, o problema termina no build em vez de virar um defeito visual difícil de rastrear.

  • sass
  • math
  • funções
  • cores
  • operações
  • depreciação

Perguntas frequentes

Por que Sass não divide mais com barra?
A barra também separa valores no CSS moderno. math.div deixa a intenção de divisão explícita e evita ambiguidade na saída.
Função Sass pode gerar seletores?
Não é esse o contrato. Função calcula e retorna valor; mixin emite declarações ou regras. Separe as responsabilidades.
color.adjust é igual a darken?
color.adjust com $lightness reduz o canal por uma quantidade fixa, a migração sugerida para darken. color.scale usa uma transformação relativa.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Dart Sass 1.103.1 (dart2js 3.13.1), Node 26.3.0, macOS, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Sass — sass:math — sass-lang.com
  2. Sass — sass:color — sass-lang.com
  3. Sass — @function — sass-lang.com
  4. Sass — Slash as division — sass-lang.com

Continue por aqui