Nidificazione dei CSS

Una delle nostre funzionalità preferite del preprocessore CSS è ora integrata nel linguaggio: le regole di stile nidificate.

Adam Argyle
Adam Argyle

Prima dell'annidamento, ogni selettore doveva essere dichiarato esplicitamente, separatamente da un altro. Ciò comporta ripetizione, dimensioni eccessive dei fogli di stile e un'esperienza di creazione frammentata.

Prima
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Dopo l'nidificazione, i selettori possono essere proseguiti e le regole di stile correlate possono essere raggruppate al loro interno.

Dopo
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Prova questa operazione nel browser.

La nidificazione aiuta gli sviluppatori a ridurre la necessità di ripetere i selettori e allo stesso tempo consente di collocare insieme le regole di stile per gli elementi correlati. Inoltre, può contribuire ad abbinare gli stili all'HTML di destinazione. Se il componente .nesting nell'esempio precedente è stato rimosso dal progetto, puoi eliminare l'intero gruppo anziché cercare nei file le istanze di selettori correlate.

L'organizzazione può essere utile per: - Organizzazione - Riduzione delle dimensioni dei file - Refactoring

La nidificazione è disponibile da Chrome 112 e può anche essere provata nella Technical Preview di Safari 162.

Introduzione all'organizzazione gerarchica CSS

Nel resto di questo post viene utilizzata la seguente sandbox di dimostrazione per aiutarti a visualizzare le selezioni. In questo stato predefinito, non è selezionato nulla e tutto è visibile. Se selezioni le varie forme e dimensioni, puoi esercitarti con la sintassi e osservarla in azione.

Una griglia colorata di cerchi, triangoli e quadrati piccoli e grandi.

All'interno della sandbox sono presenti 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 sceglierai 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

L'annidamento 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 di classi .child è nidificato all'interno del selettore di classi .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 deve essere posizionata la classe principale.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Questi due esempi sono funzionalmente equivalenti e il motivo per cui hai opzioni diventerà più chiaro man mano che verranno esplorati esempi più avanzati in questo articolo.

Selezione dei cerchi

Per questo primo esempio, l'obiettivo è aggiungere stili per attenuare e sfocare solo i cerchi all'interno della demo.

Senza nidificazione, il CSS oggi:

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

Con il 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);
  }
}

Il risultato: tutti gli elementi all'interno di .demo con una classe .circle sono sfumati e quasi invisibili:

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

Selezionare triangoli e quadrati

Questa operazione richiede la selezione di più elementi nidificati, chiamati anche selettori di gruppo.

Senza nidificazione, oggi esistono due modi per utilizzare CSS:

.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 il nidificazione, ecco due modi validi:

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

o

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

Il risultato: all'interno di .demo rimangono solo gli elementi .circle:

Nella griglia colorata di forme rimangono solo cerchi,
    tutte le altre forme sono quasi invisibili.
Prova una demo

Selezionare triangoli e cerchi di grandi dimensioni

Questa attività richiede un selettore composto, in cui gli elementi devono avere entrambe le classi per 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 il nidificazione, ecco due modi validi:

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

o

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

Il risultato: tutti i triangoli e i cerchi grandi sono nascosti all'interno di .demo:

Nella griglia colorata sono visibili solo le forme piccole e medie.
Prova una demo
Suggerimento per professionisti: selettori composti e nidificazione

Il simbolo & è il tuo migliore amico in questo caso, in quanto mostra esplicitamente come unire i selettori nidificati. Considera l'esempio seguente:

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

Sebbene sia un modo valido per nidificare, i risultati non corrisponderanno agli elementi che potresti aspettarti. 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.

Seleziona tutte le forme tranne quelle rosa

Questa operazione richiede una pseudo-classe 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 il nidificazione, ecco due modi validi:

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

o

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

Il risultato: tutte le forme non rosa sono 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 combina .demo e :not() in .demo:not(), diversamente dall'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 l'annidamento è ricca di altri esempi. Se vuoi saperne di più sulla sintassi tramite esempi, consulta questa pagina che copre una vasta gamma di esempi validi e non validi.

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

Annidamento di @media

Può essere molto distratto passare a un'altra area dello stile per trovare condizioni di query sui contenuti multimediali che modificano un selettore e i relativi stili. Questa distrazione è stata eliminata grazie alla possibilità di nidificare le condizioni direttamente all'interno del contesto.

Per comodità sintattica, se la query sui contenuti multimediali nidificata modifica 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'utilizzo 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 &, ma sceglie come target anche le schede .large per dimostrare che le funzionalità di nidificazione aggiuntive continuano a funzionare.

Scopri di più sull'nidificazione di @rules.

Nidificazione ovunque

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

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

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

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

Anche se questo esempio sembra un po' inutile, esistono sicuramente scenari in cui la possibilità di ripetere un contesto del selettore è utile.

Esempi di nidificazione non validi

Esistono alcuni scenari di sintassi nidificata non validi che potrebbero sorprenderti se hai utilizzato la nidificazione nei preprocessori.

Nidificazione e concatenazione

Molte convenzioni di denominazione delle classi CSS si basano sul fatto che l'organizzazione gerarchica possa concatenare o aggiungere i selettori come se fossero stringhe. Questo non funziona nell'annidamento CSS perché i selettori non sono stringhe, ma riferimenti a oggetti.

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

Una spiegazione più approfondita è disponibile nella specifica.

Esempio di nidificazione complessa

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

Prendi in considerazione il seguente blocco CSS nidificato:

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

Questo è il primo esempio che inizia con un elenco di selettori e poi continua a nidificarsi ulteriormente. Gli esempi precedenti terminavano solo con un elenco di selettori. Questo esempio di nidificazione non contiene errori, ma esiste un dettaglio di implementazione potenzialmente complicato relativo alla nidificazione all'interno degli elenchi di selettori, in particolare quelli che includono un selettore ID.

Affinché lo scopo dell'annidamento funzioni, qualsiasi elenco di selettori che non sia l'annidamento più interno verrà racchiuso tra :is() dal browser. Questo a capo mantiene il raggruppamento dell'elenco di selettori in tutti i contesti creati. Il gruppo :is(.one, #two) ha l'effetto collaterale di adottare la specificità del punteggio più alto all'interno dei selettori tra parentesi. Questo è il modo in cui :is() funziona sempre, ma potrebbe sorprenderti quando utilizzi la sintassi di nidificazione perché non è esattamente ciò che è stato creato. Il trucco riepilogato: l'annidamento con ID ed elenchi di selettori può portare a selettori di specificità molto elevata.

Per riepilogare chiaramente l'esempio complicato, il blocco nidificato precedente verrà applicato al documento come segue:

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

Fai attenzione o insegna ai linters ad avvisare quando si verifica il nidificazione all'interno di un elenco di selettori che utilizza un selettore ID, poiché la specificità di tutto il nidificazione all'interno di quell'elenco di selettori sarà elevata.

Combinazione di nidificazione e dichiarazioni

Prendi in considerazione il seguente blocco CSS nidificato:

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

Il colore degli elementi .card sarà blue.

Eventuali dichiarazioni di stile mescolate vengono sollevate in alto, come se fossero state create prima di qualsiasi nidificazione. Puoi trovare ulteriori dettagli nella specifica.

Esistono dei modi per aggirare il problema. Il codice seguente inserisce i tre stili di colore in &, mantenendo l'ordine di applicazione in cascata come previsto dall'autore. Il colore degli elementi .card sarà rosso.

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

In effetti, è buona norma racchiudere tutti gli stili che seguono l'annidamento con un &.

.card {
  color: green;

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

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

Rilevamento di funzionalità

Esistono due ottimi modi per rilevare il nidificazione del CSS: utilizza la nidificazione o @supports per verificare la possibilità di analizzare i selettori nidificati.

Uno screenshot della demo di Codepen di Bramus che chiede se il browser supporta il nidificazione CSS. Sotto questa domanda è presente una casella verde che indica l&#39;assistenza.

Utilizzo del nesting:

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

  .no-nesting {
    display: none;
  }
}

Utilizzo di @supports:

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

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

Debug con Chrome DevTools

Il supporto attuale in DevTools per l'annidamento è minimo. Al momento, gli stili sono rappresentati nel riquadro Stili come previsto, ma il monitoraggio del nidificazione e il relativo contesto completo del selettore non sono ancora supportati. Abbiamo un progetto e dei piani per chiarire e rendere trasparente la questione.

Uno screenshot della sintassi di nidificazione di Chrome DevTools.

Chrome 113 dovrebbe avere un supporto aggiuntivo per il nidificazione CSS. Non perderti gli aggiornamenti.

Il futuro

Nidificazione CSS è disponibile solo nella versione 1. La versione 2 introdurrà più sintassi e potenzialmente meno regole da memorizzare. La richiesta di analisi dell'organizzazione in nidificazioni non deve essere limitata o presentare difficoltà.

La nidificazione è un grande miglioramento del linguaggio CSS. Ha implicazioni per la creazione in quasi tutti gli aspetti dell'architettura del CSS. Questo grande impatto deve essere approfondito e compreso prima che la versione 2 possa essere specificata in modo efficace.

Per concludere, ecco una demo che utilizza @scope, il nidificazione e @layer tutti insieme. È tutto molto emozionante.

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