Pré-processadores CSS
1. O Problema com CSS Puro
À medida que um projeto cresce, as folhas de estilo crescem junto. Um arquivo CSS de um site real pode ter centenas ou milhares de linhas — e aí começam os problemas:
- Repetição de valores: a mesma cor ou tamanho de fonte aparece em dezenas de lugares. Mudar um exige busca-e-substituição em todo o arquivo.
- Seletores longos: para estilizar um botão dentro de um formulário dentro de um modal, você escreve
.modal .form .btn { ... }repetidas vezes. - Sem organização lógica: não existe uma forma nativa de dividir o CSS em módulos e importá-los sem overhead de performance.
/* Problema clássico: valor repetido em vários lugares */
.header { background-color: #3a86ff; }
.btn-primary { background-color: #3a86ff; }
.link-active { color: #3a86ff; }
.badge { border: 2px solid #3a86ff; }
/* Se a cor mudar, são 4 lugares para editar — e o arquivo real tem 40 */
É para resolver esses problemas que existem os pré-processadores CSS.
2. O que são Pré-processadores?
Um pré-processador CSS é uma ferramenta que estende a linguagem CSS com recursos que ela não possui nativamente, como variáveis com escopo, funções, aninhamento de seletores e módulos. Você escreve em uma linguagem estendida (.scss, .less, .styl) e uma ferramenta compila esse arquivo para CSS puro, que o navegador entende normalmente.
Arquivo .scss → Compilador → Arquivo .css → Navegador
O navegador nunca vê o arquivo fonte — ele recebe apenas o CSS gerado. Isso significa que você pode usar qualquer recurso do pré-processador sem se preocupar com compatibilidade de navegador.
Os recursos que os pré-processadores adicionam
- Variáveis — armazenar valores reutilizáveis com nome
- Nesting (aninhamento) — escrever seletores dentro de outros
- Mixins — grupos de declarações reutilizáveis, como funções
- Partials e módulos — dividir o CSS em arquivos organizados
- Herança (
@extend) — compartilhar estilos entre seletores - Operadores — cálculos matemáticos no CSS
3. Os Pré-processadores Mais Usados
Existem três opções principais no mercado:
| Pré-processador | Extensão | Sintaxe | Popularidade |
|---|---|---|---|
| Sass (SCSS) | .scss | Similar ao CSS | Dominante |
| Less | .less | Similar ao CSS | Muito usado (Bootstrap v3) |
| Stylus | .styl | Indentada, flexível | Nicho |
Sass é o mais utilizado atualmente e o escolhido para esta aula. A maioria dos frameworks CSS modernos (Bootstrap v4+, Foundation, Bulma) usa Sass internamente.
4. Sass e SCSS
Sass tem dois formatos de sintaxe:
- SCSS (
.scss) — usa chaves{}e ponto e vírgula;, igual ao CSS. É o formato recomendado. - Sass indentado (
.sass) — sem chaves nem ponto e vírgula, usa indentação. Mais conciso, mas diferente do CSS.
// SCSS — parece CSS, fácil de aprender
.botao {
background: blue;
&:hover {
background: darkblue;
}
}
// Sass indentado — sem chaves nem ponto e vírgula
.botao
background: blue
&:hover
background: darkblue
Este material usa exclusivamente a sintaxe SCSS.
Instalando e usando o Sass
A forma mais simples é instalar o Sass via npm e rodar no terminal:
npm install -g sass
Para compilar um arquivo automaticamente sempre que salvar:
sass --watch estilo.scss estilo.css
O --watch mantém o Sass rodando em segundo plano e recompila toda vez que o arquivo .scss é alterado.
Alternativa sem instalação: use o Sass Playground no navegador para testar código sem instalar nada.
5. Variáveis
Variáveis Sass começam com $ e permitem guardar qualquer valor CSS — cores, tamanhos, fontes, etc. — para reutilizar em qualquer lugar do arquivo.
// Declaração de variáveis
$cor-primaria: #3a86ff;
$cor-texto: #333;
$fonte-base: 'Inter', sans-serif;
$raio-borda: 8px;
// Uso
body {
font-family: $fonte-base;
color: $cor-texto;
}
.btn {
background: $cor-primaria;
border-radius: $raio-borda;
}
.link {
color: $cor-primaria; // mesmo valor, um lugar para mudar
}
/* CSS gerado */
body {
font-family: 'Inter', sans-serif;
color: #333;
}
.btn {
background: #3a86ff;
border-radius: 8px;
}
.link {
color: #3a86ff;
}
A vantagem fica clara quando você precisa mudar a cor primária: edita uma linha no .scss e o compilador propaga a mudança por todo o CSS gerado.
Variáveis no CSS nativo
O CSS moderno também tem variáveis — chamadas de CSS Custom Properties:
:root {
--cor-primaria: #3a86ff;
--raio-borda: 8px;
}
.btn {
background: var(--cor-primaria);
border-radius: var(--raio-borda);
}
A diferença fundamental é quando são resolvidas:
Variáveis Sass ($) | CSS Custom Properties (--) | |
|---|---|---|
| Resolvidas | Na compilação | No navegador, em tempo de execução |
| Podem ser alteradas com JS | Não | Sim |
| Suporte a cálculos | Sim, no Sass | Sim, com calc() |
| Escopo | Arquivo/bloco | Cascata CSS |
CSS Custom Properties são mais poderosas para temas dinâmicos (ex: modo escuro ativado por JS). Variáveis Sass são úteis quando o valor é fixo e definido em tempo de desenvolvimento.
6. Nesting (Aninhamento)
O CSS puro exige que você repita o seletor pai em cada regra. O Sass permite aninhar regras dentro de outras, espelhando a estrutura do HTML:
// SCSS — estrutura visual corresponde ao HTML
nav {
background: #333;
ul {
list-style: none;
margin: 0;
}
li {
display: inline-block;
}
a {
color: white;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
/* CSS gerado */
nav { background: #333; }
nav ul { list-style: none; margin: 0; }
nav li { display: inline-block; }
nav a { color: white; text-decoration: none; }
nav a:hover { text-decoration: underline; }
O operador &
O & dentro de um bloco aninhado representa o seletor pai. É essencial para pseudo-classes, pseudo-elementos e modificadores:
.botao {
background: blue;
&:hover { background: darkblue; } // .botao:hover
&:disabled { opacity: 0.5; } // .botao:disabled
&::after { content: " →"; } // .botao::after
&.ativo { background: green; } // .botao.ativo (sem espaço!)
&-primario { background: #3a86ff; } // .botao-primario (BEM)
}
Atenção ao sobreuso: aninhar mais de 3 níveis gera seletores CSS longos e específicos demais — dificulta sobrescrever estilos. A regra geral é: aninhe apenas o que reflete a estrutura semântica, não a estrutura visual.
Nesting nativo no CSS
O CSS moderno (2023+) passou a suportar aninhamento nativamente, com sintaxe praticamente idêntica ao Sass:
nav {
background: #333;
a {
color: white;
&:hover { text-decoration: underline; }
}
}
O suporte em navegadores modernos é amplo, mas projetos que precisam de compatibilidade com navegadores mais antigos ainda dependem do Sass para compilar o nesting.
7. Partials e Módulos
À medida que o projeto cresce, colocar todo o CSS em um arquivo único se torna impraticável. Sass resolve isso com partials: arquivos menores, focados em um assunto, que são importados em um arquivo principal.
Convenção de nomenclatura
Arquivos parciais começam com _ (underline). Isso indica ao Sass que o arquivo não deve gerar um .css próprio — ele existe apenas para ser importado.
scss/
├── _variables.scss ← variáveis globais
├── _reset.scss ← reset CSS
├── _typography.scss ← fontes e tamanhos
├── _buttons.scss ← estilos de botões
├── _forms.scss ← formulários
└── main.scss ← importa tudo, gera main.css
@use — sistema de módulos moderno
O @use é a forma recomendada atual (substituiu o @import que estava sendo descontinuado):
// _variables.scss
$cor-primaria: #3a86ff;
$fonte-base: 'Inter', sans-serif;
$espacamento: 16px;
// main.scss
@use 'variables' as v; // importa com namespace
@use 'reset';
@use 'buttons';
body {
font-family: v.$fonte-base; // acessa com prefixo "v."
padding: v.$espacamento;
}
Se não quiser usar namespace, use as *:
@use 'variables' as *;
body {
font-family: $fonte-base; // sem prefixo
}
@import no CSS nativo
O CSS também tem @import, mas funciona de forma diferente:
@import 'variables.css'; /* CSS puro */
A diferença crítica: o @import do CSS é processado pelo navegador — cada arquivo importado gera uma requisição HTTP separada, impactando a performance. O @use do Sass é resolvido na compilação, gerando um único arquivo .css otimizado.
8. Mixins
Mixins são blocos de declarações CSS com nome que podem ser reutilizados em qualquer seletor. Funcionam como funções: aceitam parâmetros e geram CSS diferente dependendo dos valores passados.
- Declaração:
@mixin nome-do-mixin($param) { ... } - Uso:
@include nome-do-mixin(valor)
// Declaração
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
// Uso
.modal { @include flex-center; }
.card-header { @include flex-center; }
/* CSS gerado */
.modal { display: flex; justify-content: center; align-items: center; }
.card-header { display: flex; justify-content: center; align-items: center; }
Mixins com parâmetros
O poder real dos mixins aparece com parâmetros — e especialmente com valores padrão ($param: valor):
@mixin tema($cor: #babaca) {
background: $cor;
box-shadow: 0 0 1px rgba($cor, .25);
color: #fff;
}
.info { @include tema(); } // usa padrão: #babaca
.alerta { @include tema(darkred); } // cor personalizada
.sucesso { @include tema(darkgreen); } // cor personalizada
/* CSS gerado */
.info {
background: #babaca;
box-shadow: 0 0 1px rgba(186, 186, 202, 0.25);
color: #fff;
}
.alerta {
background: darkred;
box-shadow: 0 0 1px rgba(139, 0, 0, 0.25);
color: #fff;
}
.sucesso {
background: darkgreen;
box-shadow: 0 0 1px rgba(0, 100, 0, 0.25);
color: #fff;
}
Casos de uso comuns para mixins: vendor prefixes, media queries reutilizáveis, padrões de layout recorrentes.
9. Herança com @extend
O @extend permite que um seletor herde todas as declarações de outro. É útil para compartilhar um conjunto de estilos base entre variações de um componente.
Placeholders (%)
A forma recomendada de usar @extend é com placeholders — seletores que começam com % e não geram CSS por conta própria, existindo apenas para ser estendidos:
// Placeholder — não gera CSS se não for estendido
%mensagem-base {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.sucesso {
@extend %mensagem-base;
border-color: #006400;
}
.erro {
@extend %mensagem-base;
border-color: #8b0000;
}
.aviso {
@extend %mensagem-base;
border-color: #ffcc00;
}
/* CSS gerado — Sass agrupa os seletores */
.aviso, .erro, .sucesso {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.sucesso { border-color: #006400; }
.erro { border-color: #8b0000; }
.aviso { border-color: #ffcc00; }
@mixin vs @extend — quando usar cada um
Essa é uma das decisões mais comuns ao trabalhar com Sass:
@mixin | @extend | |
|---|---|---|
| Aceita parâmetros | ✅ sim | ❌ não |
| CSS gerado | Repete as propriedades em cada seletor | Agrupa seletores (menor repetição) |
Pode ser usado dentro de @media | ✅ sim | ❌ limitado |
| Flexibilidade | Alta | Baixa |
| Risco de CSS inesperado | Baixo | Médio (agrupa seletores não relacionados) |
Regra prática: prefira @mixin na maioria dos casos. Use @extend com placeholders apenas quando o conjunto de propriedades é fixo e os seletores são realmente relacionados semanticamente.
O mesmo exemplo com mixin gera CSS diferente:
@mixin mensagem-base() {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.sucesso { @include mensagem-base(); border-color: #006400; }
.erro { @include mensagem-base(); border-color: #8b0000; }
/* CSS gerado com mixin — propriedades repetidas em cada seletor */
.sucesso { border: 1px solid #ccc; padding: 10px; color: #333; border-color: #006400; }
.erro { border: 1px solid #ccc; padding: 10px; color: #333; border-color: #8b0000; }
10. Operadores e Funções
O Sass suporta operações matemáticas diretamente no código:
$largura-total: 960px;
$colunas: 12;
$gutter: 20px;
.coluna {
width: ($largura-total / $colunas) - $gutter; // 60px
}
/* CSS gerado */
.coluna { width: 60px; }
O CSS nativo faz o equivalente com calc(), mas o cálculo é resolvido pelo navegador — não durante a compilação:
.coluna { width: calc((960px / 12) - 20px); }
Funções de cor
Uma das funcionalidades mais úteis do Sass são as funções de manipulação de cor:
$cor: #3a86ff;
.botao {
background: $cor;
&:hover { background: darken($cor, 10%); } // mais escura
&:active { background: lighten($cor, 10%); } // mais clara
&:disabled { background: desaturate($cor, 50%); } // menos saturada
}
11. Recursos Avançados
O Sass oferece recursos que vão além do CSS convencional, aproximando-o de uma linguagem de programação:
Controle de fluxo
// @if / @else
@mixin tema($modo) {
@if $modo == escuro {
background: #111;
color: #fff;
} @else {
background: #fff;
color: #111;
}
}
// @each — percorrer uma lista
$cores: red, green, blue;
@each $cor in $cores {
.badge-#{$cor} {
background: $cor;
}
}
// Gera: .badge-red, .badge-green, .badge-blue
// @for — loop numérico
@for $i from 1 through 4 {
.col-#{$i} {
width: 25% * $i;
}
}
// Gera: .col-1 (25%), .col-2 (50%), .col-3 (75%), .col-4 (100%)
12. Sass no Mundo Real
Grandes frameworks CSS usam Sass internamente para organização e customização:
- Bootstrap — usa Sass para modularização, sistema de grid e variáveis de tema customizáveis
- Foundation — usa Sass amplamente para personalização
- Bulma — usa Sass para sistema de componentes
A consequência prática: se você precisar customizar qualquer um desses frameworks (trocar cores, fontes, espaçamentos), vai editar variáveis Sass — não o CSS gerado.
Resumo de referências
| Conceito | Onde pesquisar mais |
|---|---|
| Variáveis Sass | Sass — Variables |
| CSS Custom Properties | MDN — CSS Custom Properties |
| Nesting Sass | Sass — Style Rules / Nesting |
| Nesting CSS nativo | MDN — CSS Nesting |
Partials e @use | Sass — @use |
| Mixins | Sass — Mixins |
@extend | Sass — @extend |
| Funções de cor | Sass — Color Functions |
| Controle de fluxo | Sass — @if, @each, @for |