Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

Aninhamento no Sass: o &, BEM e o limite de três níveis

O que o aninhamento vira no CSS final, como o & monta seletores BEM e quanto peso um componente aninhado fundo custa de verdade.

Rodolfo Mori4 min de leitura

Aninhamento coloca regras relacionadas dentro do mesmo bloco no arquivo SCSS. Ele melhora a leitura quando expressa a estrutura de um componente, mas pode esconder um seletor longo. O navegador não recebe “níveis”: o Sass combina cada parte e grava seletores CSS completos.

Por isso, nesta aula toda entrada aparece ao lado da saída do Dart Sass 1.103.1. Não julgue o aninhamento apenas pela beleza do fonte; julgue pelo seletor que ele produz e pela dependência criada com o HTML.

bash
npx sass --stdin --no-source-map --style=expanded

Esse comando não imprime uma mensagem de sucesso: nos casos válidos, o stdout é o próprio CSS compilado, reproduzido em cada bloco abaixo.

Antes de seguir, revise seletores e cascata. Aninhar não reduz especificidade e não transforma uma classe descendente em componente isolado.

O aninhamento mais simples vira um descendente

Uma regra escrita dentro de outra, sem &, vira uma relação de descendência:

css
.card {
  .title { color: #111827; }
}
.card .title { color: #111827; }

Isso seleciona qualquer .title dentro de .card, mesmo vários níveis abaixo. Não significa “filho direto”. Se essa era a intenção, escreva > .title. A indentação do SCSS não descreve a profundidade real do DOM.

O & aponta para o seletor pai

Pseudo-classes não devem ganhar um espaço antes delas. O & é substituído por .button e cola :hover ou :focus-visible ao seletor:

css
.button {
  &:hover { transform: translateY(-2px); }
  &:focus-visible { outline: 3px solid #a78bfa; }
}
.button:hover { transform: translateY(-2px); } .button:focus-visible { outline: 3px solid #a78bfa; }

Sem &, .button :hover procuraria um descendente em estado hover. É outro seletor e frequentemente parece funcionar por acidente quando o botão contém um ícone.

BEM com sufixo: &__element e &--modifier

Quando o seletor pai termina em nome alfanumérico, Sass permite anexar um sufixo. Isso combina bem com BEM:

css
.card {
  &__title { font-weight: 700; }
  &--featured { border-color: #6d28d9; }
}
.card__title { font-weight: 700; } .card--featured { border-color: #6d28d9; }

Note que .card__title não é descendente de .card; é uma classe independente com nome derivado. A proximidade no SCSS é organização de autoria, não uma exigência de colocar as duas classes no mesmo elemento.

Colocar o contexto antes do componente

O & também pode aparecer depois de um seletor de contexto. Aqui a regra vale quando um ancestral ativa tema escuro:

css
.card {
  [data-theme="dark"] & {
    background: #111827;
  }
}
[data-theme=dark] .card { background: #111827; }

Esse padrão é útil, mas uma custom property costuma escalar melhor para muitas cores de tema. A lição de variáveis no Sass explica por que valores que mudam no DOM pertencem ao CSS.

Filhos e irmãos sem ambiguidade

Combinadores podem iniciar a regra interna. O compilador liga o combinador ao pai mesmo sem & explícito:

css
.card {
  > .title { margin: 0; }
  + .card { margin-top: 1rem; }
}
.card > .title { margin: 0; } .card + .card { margin-top: 1rem; }

O primeiro caso exige filho direto; o segundo seleciona um card imediatamente depois de outro. São relações intencionais. Aninhar cada detalhe só porque ele aparece dentro do componente no HTML não é intencional — é acoplamento.

O limite de três níveis é uma proteção, não sintaxe

O Sass compila quatro níveis sem reclamar:

css
.page {
  .sidebar {
    .card {
      .title { color: #6d28d9; }
    }
  }
}
.page .sidebar .card .title { color: #6d28d9; }

O resultado tem especificidade 0-4-0: quatro classes. Uma simples classe de utilidade, 0-1-0, não vence na mesma origem e camada, mesmo quando aparece depois; a especificidade maior é comparada antes da ordem de declaração. Mais importante, mover o card para fora de .sidebar quebra a regra visual.

Use três níveis como alarme: componente, elemento e estado já ocupam o orçamento. Se precisar de um quarto, tente nomear a parte com uma classe própria. A aula de especificidade CSS ajuda a calcular o peso sem recorrer a !important.

Esse limite também melhora a remoção de código. Quando cada parte tem uma classe estável, buscar .card__title mostra onde ela nasce e onde é usada. Um seletor formado pela árvore inteira pode continuar no CSS depois que o HTML mudou, sem corresponder a nada. A folha cresce e ninguém se sente seguro para apagar. Um seletor curto é, portanto, uma ferramenta de manutenção, não apenas preferência de estilo.

O erro de posição do &

Como o pai pode ser um seletor de tipo, Sass só aceita & no começo de um seletor composto. Tentar colocar span antes dele falha:

css
.card {
  span& { color: red; }
}
Error: "&" may only used at the beginning of a compound selector. ╷ 2 │ span& { color: red; } │ ^ ╵ - 2:7 root stylesheet

A correção depende da intenção. Para “um span que também tem .card”, use span.card fora do bloco; para “um span dentro do card”, use span aninhado. Não troque a ordem até o compilador aceitar sem entender o seletor resultante.

Sass nesting e CSS nesting nativo

CSS moderno também aceita regras aninhadas. Para pseudo-classes, esta escrita é familiar e não requer compilação em navegadores compatíveis:

css
.button {
  &:hover {
    transform: translateY(-2px);
  }
}

No CSS nativo, a regra permanece aninhada no arquivo entregue; quando a mesma entrada passa pelo Sass, ela vira .button:hover.

A concatenação BEM &__title é o ponto que impede uma troca mecânica: nesting nativo não é um gerador geral de texto de seletor. Antes de remover Sass de um projeto, procure sufixos, mixins, maps e funções — não apenas blocos indentados.

Checklist antes de aceitar um seletor aninhado

Leia o CSS compilado e responda: o seletor tem no máximo três classes? O componente funciona se mudar de página? O estado usa & sem espaço? A relação de filho ou irmão é realmente parte do contrato? Se qualquer resposta for não, achate a regra.

css
.card {}
.card__title {}
.card:hover {}

Na contagem de especificidade, .card e .card__title têm 0-1-0; .card:hover tem 0-2-0.

O próximo passo é reutilizar declarações com mixins. O guia completo de Sass mantém o mapa da trilha e mostra quando o CSS nativo já é suficiente.

  • sass
  • aninhamento
  • bem
  • seletores
  • especificidade
  • at-root

Perguntas frequentes

Qual é o limite técnico de aninhamento no Sass?
O compilador aceita mais de três níveis, mas esse é um limite editorial útil para impedir seletores pesados e dependentes da estrutura do HTML.
O & sempre significa a classe externa?
Ele representa o seletor pai completo. Pode formar pseudo-classes, sufixos BEM ou colocar o pai dentro de um contexto.
Nesting do CSS nativo é igual ao do Sass?
A finalidade se aproxima, mas parsing, compatibilidade e alguns casos de concatenação diferem. Sempre confira o CSS gerado antes de migrar.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Dart Sass 1.103.1 (dart2js 3.13.1), Node 26.3.0, macOS, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Sass — Parent Selector — sass-lang.com
  2. Sass — Style Rules — sass-lang.com
  3. MDN — CSS nesting — developer.mozilla.org

Continue por aqui