3 coisas que você poderia estar fazendo com Sass e talvez não esteja

Camilo Micheletto
Feb 22 · 7 min read

Muito além do CSS aninhado

A Syntactically Awesome Style Sheets, ou Sass, se define por ela mesma um “CSS com superpoderes”, mas basicamente o que todo mundo pensa quando falamos sobre ela é o CSS aninhado. Entretanto, podemos ir muito além disso, usando a Sass para códigos mais enxutos, menos repetitivos e mais legíveis. Quer saber como? Neste post vou falar sobre três recursos incríveis que podem te ajudar muito no dia-a-dia. Vamos lá?

1. Código BEM aninhado

Geralmente, as pessoas optam por Sass pela possibilidade de escrever CSS de maneira aninhada:

.element {
/*...*/
.children {
/*...*/
&:hover {
/*...*/
}
}
}

Porém, algumas pessoas ainda não utilizam o parent selector (&), que simboliza a classe CSS pai do elemento em que ela está dentro:

.element {
&__modal {
/* é compilado para .element__modal */
}
}

E isso é muito útil principalmente quando seguimos um padrão de CSS como o BEM (Block — Element — Modifier), que algumas pessoas reclamam que possuem classes com nomes muito extensos. Com o Sass, conseguimos quebrar a escrita deste código logicamente usando parent selector:

.block {
&__element {
/* compila pra .modal__container*/
&--modifier {
/* compila pra .modal__container--open*/
}
}
}

Quanto mais é respeitada a estrutura de blocos, elementos e modificadores, menor a necessidade de aninhar mais de três elementos, o que chamamos de overstacking e dificulta a legibilidade do código.

Outra maneira de evitar aninhamento excessivo de código é pensar que não é só porque elementos estão dentro de um mesmo bloco que eles não podem ser tratados como blocos diferentes. Se dentro de um você tem um item que é um dropdown complexo e cheio de etapas, ao invés de escrevê-lo inteiro dentro do nav, você pode tratá-lo como um bloco à parte. Um exemplo são arquiteturas como CubeCSS, que possuem maneiras de evitar depositar estruturas muito grandes em blocos com suas globals, layouts e utilitários. Vale a pena dar uma olhada.

2. Loops e Mapas

Imagina que você tem um componente de botão que tem diversas variantes. Geralmente a galera resolve esse problema na unha escrevendo classe por classe ou, se tiver usando algum framework de Javascript, passando cada uma das propriedades CSS como props, o que é crime em 17 países segundo a ONU. Os maps e loops do Sass podem te ajudar a gerar todas essas variantes sem o trabalho braçal de escrever todas elas, dados os seguintes requisitos:

  • Não é recomendado que suas variantes sejam muito diferentes, mas que pelo menos possuam boa parte das propriedades em comum.
  • Suas variantes não podem ser editáveis via interface, pra esse fim é recomendado utilizar outra estratégia como classes utilitárias ou CSS-in-JS, que eu particularmente não gosto, mas eu tenho amigues que gostam.

Primeiro passo: agrupe suas variáveis
Vamos supor que o que varia entre esses botões é apenas a cor e a opacidade quando é :disabled, vamos usar as cores do bootstrap de exemplo. A primeira coisa a se fazer é criar um mapa com o nome da cor, a cor e a cor da fonte:

// variáveis de cor
$white: #FCFAF7;
$lightgrey: #D5D5D5;
$mediumgrey: #B1B1B1;
$darkgrey: #505155;
$primary: #34CED1;
$success: #7DCC3D;
$danger: #E64545;
$warning: #ffc107;

// Mapa de cores do botão
$buttons-map:
"primary" $primary $white,
"danger" $danger $white,
"success" $success $white,
"warning" $warning $darkgrey,
"dark" $darkgrey $white,
"secondary" $mediumgrey $white;

A sintaxe do map é bem flexível, nesse caso, cada vírgula separa uma lista com três itens, como se fosse uma array. É possível também criar uma como em objetos da seguinte forma:

$font-map: (
"heading-1": ($ft-poppins, 2.9rem, bold),
"heading-2": ($ft-poppins, 1.8rem, bold),
"subheading": ($ft-poppins, 1.375rem, 200),
"title": ($ft-noto, 1.05rem, bold),
"text": ($ft-noto, 1rem, 200),
"text-small": ($ft-noto, 0.75rem, 200)
);

Se você usa Javascript, esse map é basicamente isso aqui:

let font-map = {
"heading-1": { ft-poppins, '2.9rem', 'bold },
// ...
}

Existe uma porrada de métodos pra lidar com listas e mapas no Sass e a documentação deles é bem simples, se você quiser saber mais pode ler esse outro artigo que aborda algumas delas.

Segundo passo: montar o loop
Primeiro vamos identificar o que no botão é o código base, aquele que seja comum entre todos, pois para sermos DRY (não repetir código à toa). Para isso, não podemos permitir que hajam vários seletores com o mesmo código e para o mesmo fim.

.btn {
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
height: 44px;
min-width: 120px;
padding: 0 10px;
width: auto;
}

Agora precisamos criar o loop. Lembra que o nosso mapa tem três itens, né? Vamos iterar, ou seja, visitar cada uma das listas desse mapa e trazer cada um desses itens para variáveis que possamos usar.

.btn {
align-self: flex-end;
border: none;
border-radius: $default-radius;
cursor: pointer;
font-size: 1rem;
height: 44px;
margin-top: 28px;
min-width: 120px;
padding: 0 10px;
width: auto;
@each $name, $bg, $color in $buttons-map {
// Para cada NOME, BACKGROUND e COR em buttons-map
}
}

Se você se perguntou por que eu coloquei uma variável “nome”, é aqui que vamos utilizar essa variável com uma propriedade mara do Sass: a interpolação. Variáveis usadas dentro da interpolação vão ser compiladas e o resultado vai ser incorporado no código. Funciona como o template string em outras linguagens.

.btn {
align-self: flex-end;
border: none;
border-radius: $default-radius;
cursor: pointer;
font-size: 1rem;
height: 44px;
margin-top: 28px;
min-width: 120px;
padding: 0 10px;
width: auto;
@each $name, $bg, $color in $buttons-map {
&__#{$name} { // Aqui vai o nome do modifier
background-color: $bg; // aqui vai o background do botão
box-shadow: 1px 1px 6px 1px rgba(15, 15, 35, .1);
color: $color; // Aqui vai a cor do botão
transition:
background 0.15s ease-in-out,
box-shadow 0.15s ease-in-out;
}
}

Dessa forma, quando o Sass for compilado e esse loop computado, ele vai gerar as seguintes classes:

.btn {}
.btn__primary {}
.btn__success {}
.btn__danger {}
// ...

E você as utiliza assim:

<button class="btn btn__primary">Comprar</button>

Mas não vamos parar por aqui, né?
Você também consegue colocar as interações no loop:

.btn {
align-self: flex-end;
border: none;
border-radius: $default-radius;
cursor: pointer;
font-size: 1rem;
height: 44px;
margin-top: 28px;
min-width: 120px;
padding: 0 10px;
width: auto;
@each $name, $bg, $color in $buttons-map {
&__#{$name} {
background-color: $bg;
box-shadow: 1px 1px 6px 1px rgba(15, 15, 35, .1);
color: $color;
transition:
background 0.15s ease-in-out,
box-shadow 0.15s ease-in-out;
&:hover {
background-color: darken($bg, 5%);
box-shadow: 3px 3px 8px -7px rgba(15, 15, 35, .3);
}
&:active {
background-color: darken($bg, 10%);
}
&:focus,
&:focus-within {
box-shadow: 0 0 0 3px darken($bg, 10%);
outline: none;
}
&:disabled {
border: none;
cursor: default;
opacity: 0.55;
pointer-events: none;
user-select: none;
}
}
}

Aqui o pulo do gato é: ao invés de escrever a versão mais escura da cor ao fazer hover dentro do mapa, você pode usar uma função de cor do Sass pra tal, como ou Tem muito mais exemplos na documentação e neste meu post.

3. Abuse do mixins

Geralmente os mixins são bons em duas ocasiões:

  • Quando você precisa repetir o mesmo código várias vezes com diferentes valores.
  • Quando você precisa repetir o mesmo código em diversos lugares, mas em alguns em específico você precisa acrescentar coisas.

Um mixin de Sass possui a seguinte sintaxe:

// Declaração simples que injeta regras CSS ou uma classe dentro do lugar que você a inserir
@mixin nome-mixin {
}// E usamos o mixin assim
.element {
@include nome-mixin();
}
// Podemos passar variáveis para o mixin@mixin background($color) {
background-color: $color;
}
// E com valores default
@mixin background($color: white) {
background-color: $color;
// Caso você declare o mixin sem parâmetros, a cor será a padrão
}
// E por fim, com um bloco
@mixin background($color: white) {
background-color: $color;
@content
// Content sinaliza que podemos acrescentar coisas na declaração
do mixin
}
// E usamos assim
.element {
@include background('#CBDBAD') {
color: white;
}
}

Mixins podem ser muito poderosos! Imagine uma situação na qual você tem diversas , cada uma com 10 e cada lista vai ter uma escala de cores. Podemos criar um mixin para gerar essa escala de 10 cores:

@mixin generate-color($name, $color) {
$number: 100;
@for $i from 0 through 9 {
$counter: $i * 10%;
// Para cada numero de 1 a 9, a cor fica mais clara em 10%
$new-color: change($color, $lightness: $counter); .#{unquote($name)}-#{$number * $i} {
// Nesse caso a classe ficará algo como .blue-100
background-color: $color;
}
}
}
@include generate-color("blue", $paleblue, "color");

Se quiser saber mais sobre essas funções que eu usei, só acessar na documentação o change-color e o unquote.

E é isso! Espero que essas dicas te ajudem a explorar o Sass muito além do CSS aninhado. Gostou? Acrescentaria algo? Achou algum erro? Fique à vontade para deixar nos comentários.

E se você quiser trabalhar e aprender junto com um time muito bom de JavaScript aqui na Concrete, é só dar uma olhada aqui e se candidatar a alguma de nossas vagas. Vamos aprender juntos! Até a próxima.

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade…

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.

Camilo Micheletto

Written by

Educador/educando, perseguidor de futuros indômitos e empreendedor.

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store