Nidificazione dei CSS

Una delle nostre funzionalità di preprocessore CSS preferite è ora integrata nel linguaggio: la nidificazione delle regole di stile.

Andrea Rossi
Adam Argyle

Prima della nidificazione, ogni selettore doveva essere dichiarato esplicitamente, separatamente l'uno dall'altro. Questo porta alla ripetizione, al blocco del foglio di stile e a un'esperienza di creazione sparsa.

Prima
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

Dopo la nidificazione, i selettori possono essere continuati e le relative regole di stile possono essere raggruppate.

Dopo
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Prova questa procedura nel browser.

La nidificazione aiuta gli sviluppatori a ridurre la necessità di ripetere i selettori e a collocare insieme le regole di stile per gli elementi correlati. ma anche che gli stili si adattino al codice HTML scelto come target. Se il componente .nesting nell'esempio precedente è stato rimosso dal progetto, potresti eliminare l'intero gruppo anziché cercare nei file le istanze del selettore correlate.

La nidificazione può essere utile per: - Organizzazione - Riduzione delle dimensioni dei file - Refactoring

La nidificazione è disponibile a partire da Chrome 112 e può anche essere provata nell'Anteprima tecnica di Safari 162.

Introduzione alla nidificazione di CSS

Nel resto di questo post,la seguente sandbox demo viene utilizzata per aiutarti a visualizzare le selezioni. Con questo stato predefinito, non è selezionato nulla e tutto è visibile. Selezionando le varie forme e dimensioni, puoi esercitare la sintassi e vederla in azione.

Una griglia colorata costituita da cerchi piccoli e grandi, triangoli e quadrati.

All'interno della sandbox ci sono cerchi, triangoli e quadrati. Alcune sono piccole, medie o grandi. Altre sono blu, rosa o viola. Sono tutti all'interno dell'elemento contenente .demo. Di seguito è riportata un'anteprima degli elementi HTML che scegli come target.

<div class="demo">
  <div class="sm triangle pink"></div>
  <div class="sm triangle blue"></div>
  <div class="square blue"></div>
  <div class="sm square pink"></div>
  <div class="sm square blue"></div>
  <div class="circle pink"></div>
  …
</div>

Esempi di nidificazione

La nidificazione CSS consente di definire gli stili per un elemento nel contesto di un altro selettore.

.parent {
  color: blue;

  .child {
    color: red;
  }
}

In questo esempio, il selettore classe .child è nidificato all'interno del selettore della classe .parent. Ciò significa che il selettore .child nidificato verrà applicato solo agli elementi secondari di elementi con una classe .parent.

In alternativa, questo esempio può essere scritto utilizzando il simbolo & per indicare esplicitamente dove inserire la classe padre.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Questi due esempi sono funzionalmente equivalenti e il motivo per cui disponi di opzioni diventerà più chiaro man mano che vengono illustrati esempi più avanzati in questo articolo.

Selezione delle cerchie

Per questo primo esempio, l'attività consiste nell'aggiungere stili per sfocare e sfocare solo i cerchi all'interno della demo.

Senza nidificazione, il CSS oggi:

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

Con la nidificazione, esistono due modi validi:

/* & is explicitly placed in front of .circle */
.demo {
  & .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

o

/* & + " " space is added for you */
.demo {
  .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

Risultato: tutti gli elementi all'interno di .demo con una classe .circle sono sfocati e quasi invisibili:

La griglia colorata delle forme non ha più cerchi,
    sono molto sbiaditi sullo sfondo.
Prova una demo

Selezione di triangoli e quadrati

Questa attività richiede la selezione di più elementi nidificati, ovvero un selettore di gruppi.

Senza la nidificazione, attualmente i CSS sono disponibili in due modi:

.demo .triangle,
.demo .square {
  opacity: .25;
  filter: blur(25px);
}

oppure utilizzando :is()

/* grouped with :is() */
.demo :is(.triangle, .square) {
  opacity: .25;
  filter: blur(25px);
}

Con la nidificazione, esistono due modi validi:

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

o

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

Risultato: solo .circle elementi rimangono all'interno di .demo:

La griglia colorata delle forme rimane solo con cerchi, mentre tutte le altre forme sono quasi invisibili.
Prova una demo

Selezione di triangoli e cerchi grandi

Questa attività richiede un selettore composto in cui gli elementi devono avere entrambe le classi per poter essere selezionati.

Senza nidificazione, il CSS oggi:

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

o

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

Con la nidificazione, esistono due modi validi:

.demo {
  .lg.triangle,
  .lg.circle {
    opacity: .25;
    filter: blur(25px);
  }
}

o

.demo {
  .lg {
    &.triangle,
    &.circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

Risultato, tutti i triangoli e i cerchi grandi vengono nascosti all'interno di .demo:

La griglia colorata mostra solo forme piccole e medie.
Prova una demo
Suggerimento avanzato con selettori composti e nidificazione

Il simbolo & è tuo amico qui perché mostra esplicitamente come aggiungere i selettori nidificati. Considera l'esempio seguente:

.demo {
  .lg {
    .triangle,
    .circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

Sebbene si tratti di un metodo valido per nidificare, i risultati non corrisponderanno agli elementi che ti aspetti. Il motivo è che senza & per specificare il risultato desiderato di .lg.triangle, .lg.circle combinato, il risultato effettivo sarebbe .lg .triangle, .lg .circle; selettori discendenti.

Selezione di tutte le forme tranne quelle rosa

Questa attività richiede una pseudoclasse funzionale di negazione, in cui gli elementi non devono avere il selettore specificato.

Senza nidificazione, il CSS oggi:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

Con la nidificazione, esistono due modi validi:

.demo {
  :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

o

.demo {
  & :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

Risultato, tutte le forme non rosa vengono nascoste all'interno di .demo:

La griglia colorata è ora monocromatica e mostra solo forme rosa.
Prova una demo
Precisione e flessibilità con &

Supponiamo che tu voglia scegliere come target .demo con il selettore :not(). & è obbligatorio per:

.demo {
  &:not() {
    ...
  }
}

Questo compone .demo e :not() in .demo:not(), a differenza dell'esempio precedente che richiedeva .demo :not(). Questo promemoria è molto importante quando si vuole nidificare un'interazione :hover.

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

Altri esempi di nidificazione

La specifica CSS per la nidificazione contiene altri esempi. Se vuoi saperne di più sulla sintassi tramite esempi, consulta un'ampia gamma di esempi validi e non validi.

I prossimi esempi introdurranno brevemente una funzionalità di nidificazione CSS, per aiutarti a comprendere l'ampiezza delle funzionalità che introduce.

Nidificare i contenuti @media

Spostarsi in un'area diversa del foglio di stile per trovare le condizioni di Media Query che modificano un selettore e i suoi stili può essere molto fastidioso. Non esiste più questa distrazione grazie alla possibilità di nidificare le condizioni direttamente all'interno del contesto.

Per praticità della sintassi, se la query supporti nidificati sta modificando solo gli stili per il contesto del selettore corrente, è possibile utilizzare una sintassi minima.

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

L'uso esplicito di & può essere utilizzato anche:

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

Questo esempio mostra la sintassi espansa con & e sceglie come target anche le schede .large per dimostrare che le funzionalità di nidificazione aggiuntive continuano a funzionare.

Scopri di più sulla nidificazione delle @regole.

Nidificazione ovunque

Tutti gli esempi fino a questo punto sono continuati o aggiunti a un contesto precedente. Puoi modificare o riorganizzare completamente il contesto, se necessario.

.card {
  .featured & {
    /* .featured .card */
  }
}

Il simbolo & rappresenta un riferimento a un oggetto selettore (non una stringa) e può essere posizionato ovunque in un selettore nidificato. Può anche essere posizionato più volte:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

Sebbene questo esempio sia un po' inutile, ci sono sicuramente scenari in cui è utile ripetere un contesto del selettore.

Esempi di nidificazione non validi

Alcuni scenari di sintassi di nidificazione non sono validi e potrebbero sorprenderti se hai eseguito la nidificazione nei preprocessori.

Nidificazione e concatenazione

Molte convenzioni di denominazione delle classi CSS si basano sulla nidificazione per essere in grado di concatenare o aggiungere selettori come se fossero stringhe. Questa operazione non funziona nella nidificazione CSS in quanto i selettori non sono stringhe, ma riferimenti a oggetti.

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

Una spiegazione più approfondita è disponibile nelle specifiche.

Esempio di nidificazione ingannevole

Nidificazione all'interno degli elenchi di selettori e :is()

Considera il seguente blocco CSS nidificato:

.one, #two {
  .three {
    /* some styles */
  }
}

Questo è il primo esempio che inizia con un elenco di selettori e continua a eseguire la nidificazione. Gli esempi precedenti terminavano solo con un elenco di selettore. Non c'è nulla di valido in questo esempio di nidificazione, ma c'è un dettaglio di implementazione potenzialmente difficile sulla nidificazione all'interno di elenchi di selettori, in particolare quelli che includono un selettore ID.

Affinché la nidificazione funzioni, qualsiasi elenco di selettori che non corrisponde a quello più interno verrà aggregato con :is() dal browser. Questo wrapping mantiene il raggruppamento dell'elenco dei selettori all'interno di qualsiasi contesto creato dall'autore. L'effetto collaterale di questo raggruppamento, :is(.one, #two), è che adotta la specificità del punteggio più alto all'interno dei selettori all'interno delle parentesi. :is() funziona sempre in questo modo, ma potrebbe sorprendere l'utilizzo della sintassi di nidificazione, poiché non è esattamente ciò che è stato creato. Il trucco è riassunto: la nidificazione con ID ed elenchi di selettori può portare a selettori di specificità molto elevate.

Per riassumere chiaramente l'esempio difficile, il precedente blocco di nidificazione verrà applicato al documento come segue:

:is(.one, #two) .three {
  /* some styles */
}

Tieni gli occhi aperti o insegna ai linter ad avvisare quando vengono nidificati all'interno di un elenco di selettori che utilizza un selettore ID, poiché la specificità di tutte le operazioni di nidificazione all'interno dell'elenco di selettori sarà elevata.

Combinazione di nidificazione e dichiarazioni

Considera il seguente blocco CSS nidificato:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

Il colore degli elementi .card sarà blue.

Qualsiasi dichiarazione di stile mescolato viene issata in alto, come se fosse stata creata prima della nidificazione. Ulteriori dettagli sono disponibili nelle specifiche.

È possibile aggirarla. Di seguito, i tre stili di colore vengono inseriti in &, che mantiene l'ordine a cascata come previsto dall'autore. Il colore degli elementi .card sarà rosso.

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

È buona norma aggregare tutti gli stili successivi alla nidificazione con un &.

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

Rilevamento delle funzionalità

Esistono due ottimi modi per rilevare la nidificazione di CSS delle funzionalità: utilizzare la nidificazione o utilizzare @supports per verificare la funzionalità di analisi del selettore di nidificazione.

Uno screenshot della demo Codepen di Bramus, in cui viene chiesto se il browser supporta la nidificazione CSS. Sotto questa domanda c&#39;è un riquadro verde che indica il supporto.

Utilizzo della nidificazione:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

In uso: @supports:

@supports (selector(&)) {
  /* nesting parsing available */
}

Il mio collega Bramus ha un ottimo codepen che mostra questa strategia.

Debug con Chrome DevTools

Attualmente il supporto per la nidificazione in DevTools è minimo. Al momento, gli stili sono rappresentati nel riquadro Stili come previsto, ma non è ancora possibile tracciare la nidificazione e il contesto completo del selettore. Abbiamo un design e piani per renderlo trasparente e chiaro.

Uno screenshot della sintassi di nidificazione di Chrome DevTools.

Chrome 113 prevede di offrire supporto aggiuntivo per la nidificazione di CSS. Torna presto a trovarci.

Il futuro

La nidificazione dei CSS è disponibile solo alla versione 1. La versione 2 introdurrà più zuccheri sintattici e potenzialmente meno regole da ricordare. L'analisi della nidificazione è molto richiesta, in modo che non sia limitata o che presenti momenti difficili.

La nidificazione è un grande miglioramento al linguaggio CSS. Ha implicazioni in termini di creazione per quasi tutti gli aspetti dell'architettura CSS. Questo grande impatto deve essere esplorato e compreso a fondo prima di poter specificare la versione 2 in modo efficace.

Per concludere, ecco una demo che utilizza @scope, la nidificazione e @layer. È tutto molto emozionante!

Una scheda chiara su sfondo grigio. La scheda ha titolo e testo, alcuni pulsanti di azione e un&#39;immagine in stile cyber punk.