</> HTML5Advent
ENFRESDEITPT

// css · Web Platform Advent #7

CSS Nesting nativo: il selettore &, il supporto dei browser e le differenze con Sass

Scrivere CSS annidato senza un preprocessore. Come funziona il selettore di annidamento &, dove differisce da Sass e quali browser lo supportano oggi.

Un foglio stampato di markup HTML con una penna appoggiata sopra

Il CSS nesting ti permette di scrivere regole dentro altre regole, così gli stili che vanno insieme restano insieme. Per anni questo è stato possibile solo con un preprocessore come Sass. Ora è una funzionalità nativa del CSS, disponibile in ogni browser moderno — senza alcun passaggio di build.

L'idea di base

Invece di ripetere il selettore genitore per ogni figlio, annidi la regola figlia al suo interno. Questi due blocchi producono lo stesso risultato:

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

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

Ogni selettore annidato viene letto relativamente al suo genitore, quindi .card p è ciò che il browser applica realmente.

Il selettore di annidamento &

La e commerciale & fa riferimento al selettore genitore. Ti serve ogni volta che il selettore annidato deve collegarsi direttamente al genitore invece di descrivere un discendente — pseudo-classi, classi modificatrici e selettori composti:

.btn {
  background: #2563eb;

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

Senza la &, un semplice :hover verrebbe trattato come un discendente: .btn *:hover, che non è quasi mai ciò che vuoi. Quando scrivi un selettore annidato che inizia con un elemento o una classe (come p sopra), il browser inserisce implicitamente per te un combinatore di discendenza.

Source code on a dark editor showing function blocks nested inside curly braces
L'annidamento rispecchia la struttura già presente nel tuo codice: blocchi inseriti dentro le parentesi graffe, indentati per mostrare cosa appartiene a cosa.

Annidare le media query

Puoi annidare @media (e altre at-rule) dentro un selettore, tenendo le modifiche responsive accanto alla regola che modificano:

.sidebar {
  width: 100%;

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

Dove differisce da Sass

La sintassi assomiglia a Sass, ma le due cose non sono identiche. Le differenze che mordono più spesso:

  • Concatenazione: Sass ti permette di costruire selettori come &__title (BEM). Il CSS nesting nativo non concatena — &__title non è valido. Devi scrivere il nome completo della classe.
  • Nessuna fase di compilazione: l'annidamento nativo gira nel browser, quindi non c'è nulla da compilare né source map da gestire.
  • Specificità di &: nel CSS nativo, & si comporta come :is() e assume la specificità del selettore più specifico nella lista del genitore, cosa che può differire in modo sottile dall'output di Sass.

Supporto dei browser e fallback

Il CSS nesting nativo è supportato nelle versioni correnti di Chrome, Edge, Firefox e Safari. Le prime implementazioni richiedevano che il selettore annidato iniziasse con un simbolo (quindi scrivevi & p invece di p); la sintassi rilassata che consente un semplice selettore di elemento è ciò che viene distribuito nei browser di oggi. Se devi supportare motori più vecchi, continua a usare Sass o PostCSS — il plugin postcss-nesting compila l'annidamento nativo in CSS flat.

Riferimento rapido

VuoiScrivi
Discendente.card { p { ... } }
Pseudo-classe&:hover { ... }
Classe modificatrice&.is-active { ... }
Responsive@media (...) { ... } annidata
Concatenazione BEMnon supportata — scrivi la classe completa

L'annidamento nativo elimina uno degli ultimi grandi motivi per ricorrere a un preprocessore in un nuovo progetto. Mantieni l'annidamento poco profondo — due o tre livelli — e i tuoi fogli di stile resteranno leggibili mentre le relazioni tra i selettori restano evidenti.