SCSS como você nunca viu
Tags: scss, css, tutorial, webdev
Published: 2022-07-04 16:00:01

Olá mundo, tudo bom com ocês ? Hoje quero falar um pouco sobre scss e algumas novidades que existem / viram.

Caso queria ver o funcionamento de todas as novas features e/ou modificar algumas coisas basta acessar meu repo [scss-like-you-never-seen](https://github.com/deverebor/scss-like-you-never-seen) e seguir o passo-a-passo para visualizar. _deixa uma starzinha também ❤️_

## Antes de tudo !important

Algumas das funcionalidades que vou mostrar não possuem suporte ainda em todos os navegadores, mas é possível testa-las habilitando as flags respectivas 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 fetures aconselho a clonar o meu repo [scss-like-you-never-seen](https://github.com/deverebor/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](https://sass-lang.com/documentation/at-rules/use) recomenda utilizar o `sass` ou `dart-sass` como compilador do projeto e assim conseguindo 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

A uns anos atrás 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ê vai poder usufruir de todos os recursos do sass module.

As novidades que vieram foi justamente o `@use` que permite que você importe um arquivo de estilo dentro de outro, para ser utilizado naquele contexto.

`@foward` que permite que você importe 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 váriavel com o mesmo nome da qual alimenta aquela propriedade, visto que o @import na hora da compilação leva em consideração a ordem.

EXAMPLE:

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


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

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

```scss
@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ê vai passar para frente oque 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:

```scss
@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.

```scss
@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](https://sass-guidelin.es/pt/#o-padro-7-1) 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:

```md
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:

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

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

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

Oque 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:

```scss
@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 copia daquele estilo em outro componente na hora da compilação.
Já o extends gera uma referência para a classe original.

EXAMPLE:

```scss
/// Mixin input

@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;
}
```

```scss
/// 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 contrario 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.

```scss
section:has(div) {
  color: red;
}
```

```html
<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.

EXAMPLE:

```scss
@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, então 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. 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](https://github.com/deverebor/scss-like-you-never-seen) deixa uma star! 

Até a próxima.