DEV Community

Cover image for Iniciando no Sass com os dois pés na porta - Funções
Camilo Micheletto
Camilo Micheletto

Posted on

Iniciando no Sass com os dois pés na porta - Funções

Caso você tenha ainda não tenha lido o post anterior, ele tá aqui e nele eu ensino a configurar um compilador maroto, entender variáveis, escopo e loopings. Nesse artigo eu vou cobrir funções, mixins, blocos e cálculos detalhadamente mas sem fritar a sua mente.

Funções

Funções do Sass funcionam exatamente como as do javascript - podem ou não receber parâmetros e sempre retornam um valor, esse valor pode ser uma cor, um número, uma lista, um mapa ou uma string. As funções de Sass não reagem a eventos do DOM como as do Javascript pois ao compilar, pois o compilador avalia essas funções, retorna o resultado e passa o resultado pra CSS normal. O Sass possui também uma série de funções nativas e funções estendidas do CSS.

// funções de cor

.card {
  background: tomato;
  &:hover {
    background: darken(tomato, 10%);
  }
}


//funções matemáticas

.card {
  height: random(100) * 1px;
}


// funções estendidas do CSS

.card {
  font-size: clamp(1.75rem, 3vw, 2.1rem);
}
Enter fullscreen mode Exit fullscreen mode

É possível também escrever as funções de forma aninhada:

@for $i from 1 through 4 { 
  .color-#{$i} {
    background-color: hsl(
      floor(random(360)),
      floor(random(100) * 1%),
      floor(random(100) * 1%));
  }
}
Enter fullscreen mode Exit fullscreen mode

O que tá rolando ai (se você entendeu o que tá rolando pode pular):

  1. O loop @for diz literalmente que: PARA CADA n ENTRE 1 e 4 FAÇA

  2. Na primeira iteração a variável $i recebe o número 1, o seletor dentro do loop .color- está interpolado com a variável $i que ao ser avaliada sua interpolação resulta no seletor .color-1.

  3. Dentro de background-color tem uma função HSL cujo o todos parâmetros recebem uma função floor(). Essa função recebe um número como argumento e retorna um inteiro mais próximo dele.

  4. A função random() por sua vez recebe um número como argumento e gera um número decimal aleatório entre 1 e o número recebido.

Tudo isso gera uma paleta de cores aleatória:

Só que essa paleta é estática, o loop @for e as funções random() e floor() foram avaliadas pra valores estáticos de CSS, ou seja, uma vez no browser essas funções nunca mais serão avaliadas pois já estarão compiladas (A não ser que tu recarregue a página).

Você também pode criar suas próprias funções que podem receber nenhum, múltiplos ou um número indefinido de argumentos:

//Uma função pode receber um ou nenhum argumento
.@function bigger-size($size) {
  @return $size * 2;
}


//Pode receber valores padrões caso não recebam argumentos
@function analog-color($color, $num: 30) {
  //Caso $num não seja preenchido ele será igual a 30

  $new-color: hue-adjust($color, #{$num}deg);

  @return $new-color;
}

//Pode receber uma quantidade n de argumentos
@function auto-height($height, $selectors...) {
  //Essa função recebe uma altura e uma quantidade n de seletores
}
Enter fullscreen mode Exit fullscreen mode

Mixins

Mixins são funções que não retornam valores mas sim estilos. Um mixin recebe um nome e pode receber argumentos. O intuito do mixin é maximizar a sua capacidade de reutilizar regras de CSS com valores diferentes, tornando seu código mais limpo e menos repetitivo ou DRY (Don't Repeat Yourself).

//Um mixin pode receber um ou nenhum argumento
@mixin colorize($cor){
  //...
}


//Pode receber valores padrões caso não recebam argumentos
@mixin square($size, $radius: 0) {
  //Caso $radius não seja preenchido ele será igual a 0
}


//Pode receber uma quantidade n de argumentos
@mixin auto-height($height, $selectors...) {
  //Essa função recebe uma altura e uma quantidade n de seletores
}
Enter fullscreen mode Exit fullscreen mode

E pra utilizar um mixin, você utiliza o include()

$main-style: #33ffcc;

@mixin navbar-colors($color) {
  background: $color;
  color: complement($color);
}

.navbar {
  @include navbar-colors($main-style);
}

//CSS
.navbar {
  background: #33ffcc;
  color: #ff3366;
}
Enter fullscreen mode Exit fullscreen mode

O David Halford criou uma função de Sass que avalia uma cor em relação ao fundo e retorna preto ou branco de acordo com o contraste com o fundo. Essa função é ótima pra automatizar a seleção de cor de fonte privilegiando a legibilidade. A formula dessa função tá documentada aqui no site da W3 caso você queira conhecer mais.

//Definição do mixin

@mixin text-contrast($color) {
  $color-brightness: round((red($color)*299)+(green($color)*587)+(blue($color)*114)/1000);

  $light-color: round((red(#ffffff)*299)+(green(#ffffff)*587)+(blue(#ffffff)*114)/1000);

  @if abs($color-brightness) < ($light-color/2){
    color: white;
  } @else {
    color: black;
  }
}

//Uso
.card {
  background: #fafafa;
  .card__text {
      @include text-contrast($card-color);
  }
}
Enter fullscreen mode Exit fullscreen mode

O que tá rolando nessa função?

  1. A função round() arredonda o número recebido como argumento para o número inteiro mais próximo.

  2. As funções red(), green() e blue() recebem uma cor como argumento e retornam o seu respectivo canal.

  3. As funções de cor serão avaliadas e multiplicadas por seus respectivos valores, o produto dessa soma será dividido por 1000.

  4. A função abs() recebe como argumento um número e retorna seu valor absoluto ou seja se negativo, será convertido para positivo.

  5. SE o valor absoluto da sua cor for MENOR do que o da cor mais clara dividido por 2, ele retornará

    css color: white

    , SENÃO

    css color: black

Esse exemplo funcionando fica assim:

Content

Vamos imaginar uma situação que vamos criar um mixin de animação CSS usando @keyframes:

@mixin animation($name) {
  @keyframes $name {
     from { opacity: 0; }
     to   { opacity: 1; }
  }
}
Enter fullscreen mode Exit fullscreen mode

Só que nesse caso, se eu quiser fazer uma animação diferente eu teria que criar outro mixin né? E se dentro dos @keyframes pudéssemos passar um bloco de código pra ele executar? Ai é que entra a diretiva @content

@mixin animation($name) {
  @keyframes #{$name} {
     @content
  }
}

// Uso

.card {
  transition: animate .5s forwards ease-in;

  @include animation(animate) {
     from { opacity: 0; }
     to   { opacity: 1; }
  }
}
Enter fullscreen mode Exit fullscreen mode

Só que só fazendo dessa maneira, compensa usar só o @keyframes sozinho né? Mas e se a gente quisesse colocar os prefixes pra garantir que essas animações funcionem bem em todos os navegadores?

@mixin animation($name) {
  @-webkit-keyframes #{$name} {
    @content;
  }

  @-moz-keyframes #{$name} {
    @content;
  }

  @keyframes #{$name} {
    @content;
  }
}

// Uso

.card {
  transition: animate .5s forwards ease-in;

  @include animation(animate) {
     from { opacity: 0; }
     to   { opacity: 1; }
  }
}
Enter fullscreen mode Exit fullscreen mode

Agora esse código gerará os três @keyframes com seus respectivos prefixes. Você também consegue passar argumentos para o @content, é recomendado que se você for passar mais de um, você passe como $map, você pode ler mais sobre isso na documentação oficial.

Mixins e funções podem facilitar muito a sua vida e tornar seus códigos cada vez mais modularizáveis e limpos, esses conceitos são um pouco mais complicados que os anteriores, então sugiro ler a documentação sobre funções e mixins (que é bastante boa) porque lá eles tem bastante exemplos, recomendo principalmente para as funções nativas de cores, que são as mais utilizadas.


No próximo artigo eu vou usar o que vimos aqui pra construir um gerador de paleta de cores para componentes, que nem esse aqui. Se isso foi útil pra você, compartilha com quem você acha que isso vai ajudar. Dúvidas, sugestões? Comente ou manda um salve lá no meu Twitter @lixeletto.

Latest comments (0)