O que é Sass?
Sass significa Syntactically Awesome Style Sheets. Ele é um pré-processador CSS — uma linguagem que estende o CSS puro com recursos de programação e é compilada para o CSS padrão que os navegadores conseguem entender. Se você já se viu repetindo valores de cores, duplicando media queries ou navegando por centenas de linhas de CSS plano, o Sass é a ferramenta que resolve esses problemas.
Criado por Hampton Catlin em 2006, o Sass foi o primeiro pré-processador CSS a ganhar adoção generalizada. Ele introduziu conceitos de linguagens de programação de propósito geral — variáveis, aninhamento (nesting), funções, loops e módulos — no mundo das folhas de estilo. Hoje, ele é a base de projetos como Bootstrap, Foundation e inúmeros design systems.
A melhor maneira de pensar no Sass é como um CSS com uma caixa de ferramentas. Você escreve arquivos .scss ou .sass usando os recursos do Sass, passa-os por um compilador e recebe arquivos .css puros que o navegador pode carregar. Não há custo de execução (runtime). Todo o poder reside inteiramente no seu fluxo de desenvolvimento.
Sass vs CSS: o que muda?
O CSS puro é uma linguagem declarativa — você descreve como os elementos devem parecer, mas não consegue criar abstrações, reutilizar lógica ou organizar o código além de separar as coisas em arquivos distintos. O Sass resolve cada uma dessas limitações:
| Capacidade | CSS Puro | Sass |
|---|---|---|
| Variáveis | Custom properties (--var) |
$variable com escopo completo |
| Nesting | Básico (agora disponível no CSS) | Maduro, com seletores de pai (&) |
| Reutilização | Copiar e colar ou classes utilitárias | Mixins, funções e extends |
| Organização | Apenas @import |
@use, @forward, partials |
| Lógica | Nenhuma | @if, @each, @for, @while |
| Matemática | Apenas calc() |
Aritmética completa em qualquer valor |
| Cores | Valores fixos | lighten, darken, mix e mais |
Sintaxe Sass vs SCSS
O Sass suporta duas sintaxes:
SCSS (.scss) — a mais comum. Ela utiliza chaves e pontos e vírgulas, exatamente como o CSS. Qualquer arquivo CSS válido é automaticamente um SCSS válido. Isso torna a adoção imediata:
/* style.scss */
$primary: #3498db;
.button {
background: $primary;
color: white;
&:hover {
background: darken($primary, 10%);
}
}
Sintaxe indentada (.sass) — a original. Ela utiliza indentação e quebras de linha em vez de chaves e pontos e vírgulas, tornando-a mais concisa, porém menos familiar:
/* style.sass */
$primary: #3498db
.button
background: $primary
color: white
&:hover
background: darken($primary, 10%)
SCSS é a sintaxe que você encontrará em praticamente todos os projetos modernos. A menos que você tenha um motivo específico para escolher o Sass indentado, use .scss.
Por que o Sass existe
O Sass tornou-se o padrão da indústria por resolver problemas reais. Os principais problemas que ele soluciona são:
Repetição. Sem variáveis, alterar uma única cor significa fazer um “Localizar e Substituir” em todos os arquivos. As variáveis do Sass permitem que você altere um valor uma única vez e o atualize em todo o projeto.
Estrutura plana. Componentes profundamente aninhados produzem seletores longos e repetitivos como .card .card-header .card-title. O aninhamento (nesting) do Sass espelha a hierarquia do HTML nos seus estilos.
Falta de reuso. O CSS não possui o conceito de um bloco de estilos reutilizável. Um componente de botão com 10 variantes significaria 10 blocos quase idênticos. Os mixins e extends do Sass eliminam essa duplicação.
Ausência de lógica. Gerar uma paleta de cores, alternar cores de linhas ou criar breakpoints responsivos a partir de uma lista exige ferramentas externas. O Sass oferece loops e condicionais diretamente na folha de estilo.
Organização. Importar dezenas de arquivos CSS com @import cria um namespace global plano onde conflitos de nomes são inevitáveis. Os módulos do Sass (@use, @forward) resolvem isso através de namespacing.
Variáveis
As variáveis são o recurso mais simples e impactante do Sass. Uma variável armazena um valor que você pode reutilizar em toda a sua folha de estilo:
/* style.scss */
$primary: #3498db;
$secondary: #2ecc71;
$font-stack: 'Helvetica Neue', Arial, sans-serif;
$spacing-unit: 8px;
body {
font-family: $font-stack;
}
.container {
padding: $spacing-unit * 3;
}
.btn-primary {
background: $primary;
color: white;
}
Altere $primary apenas uma vez no topo e todos os elementos que a referenciam serão atualizados automaticamente. As variáveis do Sass são constantes de tempo de compilação — elas não existem no CSS de saída. Isso é diferente das propriedades customizadas do CSS (--var), que residem no navegador em tempo de execução. Use variáveis Sass para valores que não precisam mudar dinamicamente.
As variáveis possuem escopo. Uma variável declarada dentro de uma regra ou mixin é local àquele bloco. Use !global para sobrescrever uma variável global de dentro de um escopo local, embora isso seja raramente necessário:
/* style.scss */
$color: red; // global
.box {
$color: blue; // local — only exists inside .box
color: $color;
}
// $color is still red here
Aninhamento (Nesting)
O aninhamento permite que você escreva seletores filhos dentro de seus pais, espelhando a estrutura do HTML e mantendo estilos relacionados agrupados:
/* style.scss */
.nav {
display: flex;
gap: $spacing-unit * 2;
&__item {
padding: $spacing-unit;
&--active {
font-weight: bold;
border-bottom: 2px solid $primary;
}
&:hover {
background: rgba($primary, 0.1);
}
}
&__logo {
margin-right: auto;
}
}
Isso é compilado para:
/* compiled.css */
.nav { display: flex; gap: 16px; }
.nav__item { padding: 8px; }
.nav__item--active { font-weight: bold; border-bottom: 2px solid #3498db; }
.nav__item:hover { background: rgba(52, 152, 219, 0.1); }
.nav__logo { margin-right: auto; }
O seletor pai & é essencial. Ele faz referência ao seletor pai, portanto, &__item dentro de .nav torna-se .nav__item. Sem o &, o Sass trata o e comercial como o contexto do pai. Você também pode usar & para pseudo-classes e pseudo-elementos em vez de aninhá-los como blocos separados.
Embora o CSS nativo agora suporte aninhamento básico, o aninhamento do Sass é mais maduro — ele suporta & para referências arbitrárias ao pai, funciona em qualquer lugar e foi testado em produção por mais de uma década.
Partials e imports
Partials são arquivos Sass destinados a serem importados, e não compilados individualmente. Nomeie-os com um prefixo de sublinhado — _variables.scss, _buttons.scss, _mixins.scss — e o Sass irá ignorá-los durante a compilação direta:
// _variables.scss
$primary: #3498db;
$spacing: 8px;
$font-stack: 'Helvetica Neue', Arial, sans-serif;
// _buttons.scss
@use 'variables' as *;
.button {
padding: $spacing * 2;
background: $primary;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
// main.scss
@use 'variables' as *;
@use 'buttons';
@use 'layout';
@use 'typography';
A regra @use importa um arquivo como um módulo. Você então acessa seus membros através de um namespace, ou usa as * para trazer tudo para o escopo. Isso mantém seu namespace global limpo e evita colisões de nomes entre arquivos.
Módulos: @use e @forward
A regra @import está obsoleta. Ela mesclava todos os arquivos em um único escopo global, o que significava que um $primary em um arquivo poderia sobrescrever silenciosamente um $primary em outro. As substituições modernas são @use e @forward.
@use
@use importa um módulo e atribui a ele um namespace:
/* style.scss */
@use 'variables';
.button {
background: variables.$primary;
padding: variables.$spacing * 2;
}
Você pode criar um alias para o namespace ou trazer todos os membros para o escopo:
/* style.scss */
@use 'variables' as v;
@use 'variables' as *; // no namespace needed
@forward
@forward re-exporta os membros de um módulo para que os arquivos que importam o módulo atual tenham acesso a eles. É utilizado para criar barrel files — um único ponto de entrada que expõe múltiplos módulos:
// _index.scss
@forward 'variables';
@forward 'mixins';
@forward 'functions';
// main.scss
@use 'index' as *; // gets everything from variables, mixins and functions
Use @forward com show e hide para controlar quais membros serão re-exportados:
/* style.scss */
@forward 'variables' show $primary, $secondary;
@forward 'mixins' hide $internal-helper;
Mixins
Mixins são blocos de estilos reutilizáveis que você pode parametrizar e incluir em qualquer lugar. Pense neles como funções que geram declarações CSS:
/* mixins.scss */
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin respond-to($breakpoint) {
@if $breakpoint == 'tablet' {
@media (min-width: 768px) { @content; }
} @else if $breakpoint == 'desktop' {
@media (min-width: 1024px) { @content; }
}
}
.hero {
@include flex-center;
min-height: 100vh;
@include respond-to('desktop') {
min-height: 80vh;
}
}
.card {
@include flex-center;
padding: 1rem;
}
Mixins podem ter parâmetros padrão, aceitar qualquer número de argumentos e usar @content para aceitar um bloco de estilos de quem os chama. Eles são o principal mecanismo de abstração no Sass — design systems, helpers responsivos e camadas de compatibilidade entre navegadores são todos construídos com mixins.
Functions
As funções do Sass computam e retornam um valor. Elas são semelhantes aos mixins, mas em vez de gerar CSS, elas produzem um valor que você pode atribuir:
/* functions.scss */
@function spacing($n) {
@return $n * 8px;
}
@function shade($color, $percentage) {
@return mix(black, $color, $percentage);
}
.hero {
padding: spacing(4); // 32px
background: shade(#3498db, 20%);
}
.sidebar {
padding: spacing(2); // 16px
}
O Sass vem com diversas funções integradas para cores (lighten, darken, saturate, adjust-hue), strings (str-length, str-insert), matemática (abs, min, max, round) e listas (length, nth, append, index). Você também pode escrever as suas próprias para lógicas específicas do projeto.
Extends e herança
A regra @extend permite que um seletor herde os estilos de outro. O Sass mescla os dois seletores em uma única regra no CSS de saída:
/* style.scss */
%message {
padding: 1rem;
border-radius: 4px;
margin-bottom: 1rem;
}
.success {
@extend %message;
background: #d4edda;
color: #155724;
}
.error {
@extend %message;
background: #f8d7da;
color: #721c24;
}
.warning {
@extend %message;
background: #fff3cd;
color: #856404;
}
Compila para:
/* compiled.css */
.success, .error, .warning {
padding: 1rem;
border-radius: 4px;
margin-bottom: 1rem;
}
.success { background: #d4edda; color: #155724; }
.error { background: #f8d7da; color: #721c24; }
.warning { background: #fff3cd; color: #856404; }
Placeholders (seletores que começam com %) não são exportados para o CSS por conta própria — eles só aparecem quando são estendidos. Isso evita regras vazias no seu arquivo compilado.
Use @extend para padrões estruturais compartilhados. Para qualquer coisa que exija parâmetros, use um mixin — @extend não pode aceitar argumentos.
Operadores
O Sass suporta os operadores aritméticos padrão para trabalhar com números:
/* style.scss */
$column-count: 12;
$gutter: 24px;
$gap: $gutter / 2; // 12px
$base: 16px;
$heading-1: $base * 2; // 32px
$heading-2: $base * 1.5; // 24px
$full-width: 100%;
$sidebar: $full-width / 3; // 33.333%
// Remainder
$remainder: 17 % 5; // 2
O Sass também suporta interpolação de strings, operadores de comparação e operadores booleanos:
/* style.scss */
$primary: #3498db;
$dark: darken($primary, 20%);
$is-dark: true;
@mixin theme-bg {
@if $is-dark {
background: $dark;
} @else {
background: $primary;
}
}
Fique atento que a divisão (/) agora é tratada como uma fração CSS em alguns contextos (ex: font: 16px/1.5). Envolva as divisões em math.div() para evitar ambiguidades, ou use calc() para divisões dinâmicas.
Fluxo de controle
O Sass inclui condicionais e loops que geram CSS no momento da compilação:
@if / @else
/* style.scss */
$theme: 'light';
@mixin theme-bg {
@if $theme == 'light' {
background: white;
color: black;
} @else if $theme == 'dark' {
background: #1a1a2e;
color: white;
} @else {
background: #f0f0f0;
color: #333;
}
}
@each
Itera sobre uma lista ou mapa:
/* style.scss */
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
);
@each $name, $color in $colors {
.text-#{$name} {
color: $color;
}
.bg-#{$name} {
background: $color;
}
}
@for
Gera um intervalo de seletores:
/* style.scss */
@for $i from 1 through 12 {
.col-#{$i} {
width: ($i / 12) * 100%;
}
}
@for $i from 1 through 5 {
.mt-#{$i} {
margin-top: $i * 8px;
}
}
@while
Executa o loop enquanto uma condição for verdadeira:
/* style.scss */
$columns: 12;
$i: $columns;
@while $i > 0 {
.col-#{$i} {
width: ($i / $columns) * 100%;
}
$i: $i - 1;
}
Maps e listas
O Sass possui estruturas de dados de primeira classe para coleções.
Lists são ordenadas e separadas por vírgulas ou espaços:
/* style.scss */
$breakpoints: 480px, 768px, 1024px, 1280px;
@each $bp in $breakpoints {
@media (min-width: $bp) {
.container {
max-width: $bp;
}
}
}
// Lists can be nested
$margins: (8px, 16px, 24px, 32px);
Maps são pares de chave-valor, semelhantes a objetos ou dicionários:
/* style.scss */
$theme: (
primary: #3498db,
secondary: #2ecc71,
bg: white,
text: #333,
);
@each $key, $value in $theme {
--color-#{$key}: #{$value};
}
Você pode acessar valores de maps com map-get, mesclá-los com map-merge, verificar a existência com map-has-key e iterar com @each.
Funções integradas do Sass
O Sass vem com uma biblioteca padrão robusta:
/* style.scss */
// Colour manipulation
$primary: #3498db;
.lighter { color: lighten($primary, 20%); }
.darker { color: darken($primary, 15%); }
.desaturated { color: desaturate($primary, 30%); }
.hue-shifted { color: adjust-hue($primary, 30deg); }
// Colour functions
$alpha: rgba($primary, 0.5); // semi-transparent
$contrast: contrast-color($primary); // contrast-safe colour
// Maths
$rounded: round(3.14); // 3
$limited: clamp(1, 10, 5); // 5
$half: math.div(100%, 2); // 50%
// Strings
$name: to-upper-case('sass'); // SASS
$length: str-length('hello'); // 5
$joined: str-insert('hello', ' world', 6); // 'hello world'
// Lists
$items: append(1px, 2px, 3px, 4px);
$first: nth($items, 1); // 1px
$count: length($items); // 4
Essas funções estão disponíveis globalmente no SCSS e através de @use 'sass:color', @use 'sass:math', @use 'sass:string', @use 'sass:list' e @use 'sass:map'.
Como usar Sass
Dart Sass
O Dart Sass é a implementação canônica e a única mantida ativamente do Sass. Instale-o com:
npm install sass
Depois, compile os arquivos diretamente:
npx sass src/styles.scss dist/styles.css
Integração com ferramentas de build
Na maioria dos projetos modernos, o Sass é gerenciado pelo seu bundler. Vite, webpack, Parcel e esbuild suportam Sass nativamente:
Vite — basta instalar sass e importar arquivos .scss:
import './styles.scss';
webpack — adicione sass-loader:
module.exports = {
module: { rules: [{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }] }
};
Compilação via CLI
# Watch mode — recompile on every save
npx sass --watch src:dist
# One compile
npx sass src/styles.scss dist/styles.css
# Output compressed CSS
npx sass --style=compressed src/styles.scss dist/styles.css
Melhores práticas
- Use a sintaxe SCSS. Ela é compatível com CSS, amplamente adotada e muito mais legível do que a sintaxe indentada.
- Use
@usee@forward, nunca@import. O sistema de importação está obsoletado e causa poluição do escopo global. - Organize com partials. Uma responsabilidade por arquivo:
_variables.scss,_mixins.scss,_buttons.scss,_layout.scss. - Crie namespaces para seus módulos. Use
@use 'module' as varou deixe o namespace padrão (module.$var) esclarecer de onde vêm os valores. - Use placeholders para padrões compartilhados. Seletores
%placeholdersó geram CSS quando são estendidos, mantendo a saída enxuta. - Escreva mixins parametrizados em vez de extends. Mixins são mais flexíveis e produzem um CSS explícito e previsível.
- Mantenha a lógica de negócio fora das folhas de estilo. Funções e loops do Sass pertencem ao seu pipeline de build, não à lógica do seu componente.
- Faça o lint do seu Sass. Use
stylelintcom um plugin de Sass para detectar depreciações e aplicar convenções. - Gere CSS compactado para produção. Use
--style=compressedou deixe que seu bundler faça a minificação. - Evite seletores profundamente aninhados. Dois a três níveis são suficientes. Aninhamentos mais profundos geralmente indicam um problema de nomenclatura ou de estrutura.