SCSS como você nunca viu!

Lucas Souza
Juntos Somos Mais
Published in
6 min readJan 12, 2023
imagem mostrando a logo do scss

Olá, mundo! Tudo bem com ocês ? Hoje quero falar um pouco sobre SCSS e algumas novidades.

Caso queira ver o funcionamento de todas as novas features e/ou modificar algumas coisas, basta acessar meu repo scss-like-you-never-seen e seguir o passo-a-passo para visualizar. Deixa uma starzinha também ❤️

Importante saber antes de tudo!

Algumas das funcionalidades que vou mostrar ainda não possuem suporte em todos os navegadores, mas é possível testá-las habilitando as respectivas flags em seu navegador.

EX: chrome://flags

Basta, agora, procurar a flag desejada, habilitar e reiniciar o navegador.

Para ter uma leitura mais agradável e ver cada uma das features, aconselho a clonar o meu repo scss-like-you-never-seen e rodar ele localmente. Dentro de cada pasta do repo existe um README.md explicando a feature.

Eu posso utilizar essas features?

A documentação do SASS recomenda utilizar o sass ou dart-sass como compilador do projeto, conseguindo, assim, usar todas essas features sem problema. Caso você esteja utilizando ruby-sass ou lib-sass, por exemplo, acredito que não será capaz, visto que está deprecated.

Sass module mode

Há um tempo foi lançado um feature no scss que é chamado de scss modules. Basicamente, ela permite que o seu estilo funcione como um modulo da aplicação, assim liberando alguns recursos interessantes.

Existem duas formas de se utilizar o sass module:

nome.module.scss ou _nome.scss

Nas duas formas você poderá usufruir de todos os recursos do sass module.

As novidades que vieram foram justamente os:

@use, que permite importar um arquivo de estilo dentro de outro para ser utilizado naquele contexto.

@foward que permite importar um arquivo de estilo dentro de outro e que ele seja passado para frente na importação.

Porque o @import é um problema ?

Usando o @import no scss encontramos um problema, um arquivo que possui, por exemplo, margin: 5rem; no final pode ficar com margin: 10rem; caso tenha alguma variável com o mesmo nome da qual alimenta aquela propriedade, visto que o @import na hora da compilação leva em consideração a ordem.

EXEMPLO:

@import "spacings"; // margin: 10rem;
@import "variables";// margin: 5rem;
@import "mixins";
@import "colors";


.container {
margin: var(--margin); // essa margin vem do variables
}s

Caso a gente altere a ordem de importação, na hora que ocorrer a compilação será alterado o valor.

@import "variables";// margin: 5rem;
@import "spacings"; // margin: 10rem;
@import "mixins";
@import "colors";


.container {
margin: var(--margin); // essa margin vem do spacings
}

O sass compila de forma procedural, ou seja, o valor da propriedade vai ser alterado de acordo com a última variável encontrada.

O problema que o @use e @foward resolve

@foward

Ele é similar ao @import, você passará para frente o que estiver em um contexto, não haverá sobre escrita.

@use

É utilizado no contexto e recebe um namespace, então se o meu arquivo se chama util tudo que eu utilizar ali será necessário passar o util como prefixo.

EX:

@use "_util";

.container {
margin: util.$margin;
}

Caso não queria usar o namespace, esteja em processo de migração ou deseja utilizar outro nome porque o atual é grande, basta utilizar as e colocar um alias.

@use "_util" as u; // o prefixo agora é `u`
@use "_animations" as *; // não será necessário passar o namespace

7–1 pattern scss

“One file to RULE them all.

One file to FIND them.

One file to BRING them all.

And in the sass way MERGE them”.

Esse é o pattern mais utilizado para desfrutar do scss modules, ou seja, o scss modules é um modo de modularizar, cada arquivo é um componente e, cada componente, é um modulo. A sua estrutura é a seguinte:
abstracts, vendors, base, layout, components, pages e themes

Existem vários patterns 4–1, 5–1 etc. Tudo vai depender da sua necessidade.

Particularmente utilizo bastante esse para meus projetos:

styles/
|
|– base/
| |– _reset.scss # Reset/normalize
| |– _color.scss # Paleta de cores da aplicação
| |– _typography.scss # Typography rules
| |– _index.scss # File used to import all base
|
|– layout/
| |– _navigation.scss # Navigation
| |– _grid.scss # Grid system
| |– _header.scss # Header
| |– _footer.scss # Footer
| |– _sidebar.scss # Sidebar
| |– _forms.scss # Forms
|
|– pages/ # Base views -> HOME, ABOUT, CONTACT etc.
| |– _home.scss # Home specific styles
| |– _contact.scss # Contact specific styles
|
|– themes/
| |– _theme.scss # Default theme
|
|– abstract/
| |– _variables.scss # Sass Variables
| |– _functions.scss # Sass Functions
| |– _mixins.scss # Sass Mixins
| |– _index.scss # File used to import all abstracts
|
`– _index.scss # Main Sass file

Container Queries

Para utilizar o @container é necessário definir um query para o componente, fazemos isso da seguinte forma:

.nosso-wrapper {
container-name: wrapper;
container-type: inline-size;
}

O que fizemos acima foi definir o tipo do container e o nome dele.

Note que o @container tem o mesmo funcionamento do @media, entretanto, o que diferencia os dois é que o container vai ter o adicional de poder utilizar operadores lógicos para definir o tamanho do container.

O que também diferencia o @container do @media é que ele ajusta o tamanho dos elementos baseado na classe pai e não pelo tamanho do viewport.

EX:

@container wrapper (inline > 50px) {
.nossa-classe {
display: grid;
align-items: center;
justify-content: center;
}
}

Compatibilidade: Chrome(🚧Beta), Firefox(🚧Beta), Chromium(🚧Beta) & Safari(✅Suportado)

Extend Rule

O extend é um recurso em que você replica o mesmo estilo de uma classe em outra.

Mas qual a diferença entre o @mixin e o @extend?

O mixin vai gerar uma cópia daquele estilo em outro componente na hora da compilação.
Já o extends, gera uma referência para a classe original.

EXEMPLO:

@mixin placeHolder {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe1 {
@include placeholder;
}
.classe2 {
@include placeholder;
}

/// Mixin output
.classe1 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe2 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
/// Extend input
.placeHolder {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe1 {
@extend %placeHolder;
}
.classe2 {
@extend %placeHolder;
}

/// Extend output
.classe1,
.classe2 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}

Apesar do @extend ser mais simples, ele é tão poderoso quanto @mixin. Mas isso pode causar alguns problemas.

  • Como a classe .placeHolder é copiada para duas classes, elas são independentes e não se comportam como se fossem uma única classe.
  • Dependendo do comportamento da classe, a classe pai pode não ser a classe original.

Quando usar ou não o @extend?

  • Mixin: utilize para gerar seu código de modo dinâmico através de variáveis.
  • Extend: utilize para elementos comuns mas que haverá pouca repetição.

Quando for necessário criar algum tipo de automatização, utilize o @mixin, caso contrário utilize o @extend, ou até mesmo os dois juntos.

Compatibilidade: Chrome(✅Suportado), Firefox(✅Suportado), Chromium(✅Suportado) & Safari(✅Suportado)

Has Selector

É uma pseudo classe que permite ao usuário selecionar um elemento do DOM e manipular caso o mesmo exista. Ele não pode ser utilizado dentro de classes css, somente selecionando seletores para seletores.

section:has(div) {
color: red;
}
<section>
<h1>Has Selector</h1>
<div>
<p>Message</p>
</div>
</section>

Compatibilidade: Chrome(🚧Beta), Firefox(🚧Beta), Chromium(🚧Beta) & Safari(✅Suportado)

Layer Rule

Define uma camada de cascata para ser trabalhada, as regas farão parte daquele contexto, não do escopo global da view.

EXEMPLO:

@layer base, component;

@layer base {
.button {
background: #eee;
border: 1px solid #ccc;
border-radius: 3px;
color: #333;
padding: 10px;
margin: 10px;
}
}

@layer component {
.button {
&__title {
font-size: 1.5rem;
font-weight: bold;
}
&__icon {
margin-right: 0.5rem;
}
}
}

A ordem de declaração de camadas é importante, pois a camada mais acima será a camada mais próxima do contexto. Caso você altere a ordem, a prioridade do estilo também mudará.

A propriedade layer pode ser útil para resolver problemas de prioridade, não sendo mais necessário usar o atributo important.

Compatibilidade: Chrome(✅Suportado), Firefox(✅Suportado), Chromium(✅Suportado) & Safari(✅Suportado)

Conclusão

Ufa! Foram muitas coisas que conseguimos ver hoje, mas algumas ainda estão em estado de desenvolvimento e será necessário ativar flags do seu navegador para testar.

Caso queria ver o código funcional de cada funcionalidade apresentada aqui, basta acessar o meu repo scss-like-you-never-seen deixa uma star!

Até a próxima!

--

--