</> HTML5Advent
ENFRESDEITPT

// css · Web Platform Advent #7

CSS Nesting nativo: o seletor &, o suporte dos navegadores e as diferenças com o Sass

Escrever CSS aninhado sem um pré-processador. Como funciona o seletor de aninhamento &, onde difere do Sass e quais navegadores o suportam hoje.

Uma folha impressa de marcação HTML com uma caneta apoiada sobre ela

O CSS nesting permite escrever regras dentro de outras regras, de modo que estilos que pertencem juntos permaneçam juntos. Durante anos isso só foi possível com um pré-processador como o Sass. Agora é um recurso nativo do CSS, disponível em todos os navegadores modernos — sem nenhuma etapa de build.

A ideia básica

Em vez de repetir o seletor pai para cada filho, você aninha a regra filha dentro dele. Estes dois blocos produzem o mesmo resultado:

/* Flat, traditional CSS */
.card { padding: 1rem; }
.card h2 { margin: 0; }
.card p { color: #555; }

/* Nested */
.card {
  padding: 1rem;
  h2 { margin: 0; }
  p { color: #555; }
}

Cada seletor aninhado é lido em relação ao seu pai, portanto .card p é o que o navegador realmente aplica.

O seletor de aninhamento &

O e comercial & refere-se ao seletor pai. Você precisa dele sempre que o seletor aninhado tiver de se conectar diretamente ao pai em vez de descrever um descendente — pseudo-classes, classes modificadoras e seletores compostos:

.btn {
  background: #2563eb;

  &:hover { background: #1d4ed8; }   /* .btn:hover */
  &.is-active { background: #1e40af; } /* .btn.is-active */
}

Sem o &, um simples :hover seria tratado como um descendente: .btn *:hover, o que quase nunca é o que você quer. Quando você escreve um seletor aninhado que começa com um elemento ou classe (como p acima), o navegador insere implicitamente um combinador de descendência para você.

Source code on a dark editor showing function blocks nested inside curly braces
O aninhamento espelha a estrutura já presente no seu código: blocos colocados dentro das chaves, indentados para mostrar o que pertence a quê.

Aninhar media queries

Você pode aninhar @media (e outras at-rules) dentro de um seletor, mantendo os ajustes responsivos ao lado da regra que eles modificam:

.sidebar {
  width: 100%;

  @media (min-width: 768px) {
    width: 280px;
  }
}

Onde difere do Sass

A sintaxe parece o Sass, mas os dois não são idênticos. As diferenças que mais costumam morder:

  • Concatenação: o Sass permite construir seletores como &__title (BEM). O CSS nesting nativo não concatena — &__title é inválido. Você precisa escrever o nome completo da classe.
  • Nenhuma etapa de compilação: o aninhamento nativo roda no navegador, então não há nada para compilar nem source maps para gerenciar.
  • Especificidade do &: no CSS nativo, & comporta-se como :is() e assume a especificidade do seletor mais específico da lista do pai, o que pode diferir sutilmente da saída do Sass.

Suporte dos navegadores e fallback

O CSS nesting nativo é suportado nas versões atuais de Chrome, Edge, Firefox e Safari. As primeiras implementações exigiam que o seletor aninhado começasse com um símbolo (então você escrevia & p em vez de p); a sintaxe relaxada que permite um simples seletor de elemento é o que é distribuído nos navegadores de hoje. Se você precisar dar suporte a motores mais antigos, continue usando Sass ou PostCSS — o plugin postcss-nesting compila o aninhamento nativo em CSS plano.

Referência rápida

Você querEscreva
Descendente.card { p { ... } }
Pseudo-classe&:hover { ... }
Classe modificadora&.is-active { ... }
Responsivo@media (...) { ... } aninhada
Concatenação BEMnão suportada — escreva a classe completa

O aninhamento nativo remove um dos últimos grandes motivos para recorrer a um pré-processador em um novo projeto. Mantenha o aninhamento raso — dois ou três níveis — e suas folhas de estilo permanecem legíveis enquanto as relações entre os seletores permanecem óbvias.