SCSS como você nunca viu!
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!