I livelli a cascata saranno in arrivo per il tuo browser

Una Kravets
Una Kravets

I livelli Cascade (la regola CSS @layer) saranno disponibili in Chromium 99, Firefox 97 e Safari 15.4 Beta. Consentono un controllo più esplicito dei file CSS per evitare conflitti tra le specifiche degli stili. Questa funzionalità è particolarmente utile per codebase di grandi dimensioni, sistemi di progettazione e quando si gestiscono stili di terze parti nelle applicazioni.

La disposizione chiara del CSS evita override di stile imprevisti e promuove un'architettura CSS migliore.

Specificità CSS e cascata

La specificità CSS è il modo in cui CSS decide quali stili applicare a determinati elementi. I diversi selettori che puoi utilizzare determinano la specificità di qualsiasi regola di stile. Ad esempio, gli elementi sono meno specifici delle classi o degli attributi, che a loro volta sono meno specifici degli ID. Questa è una parte elementare dell'apprendimento dei CSS.

La gente si affida alle convenzioni di denominazione CSS, come BEM, per evitare di ignorare involontariamente la specificità. Assegnando a ogni elemento un unico nome di classe, tutto viene posizionato sullo stesso piano di specificità. Tuttavia, non è sempre possibile mantenere questi stili organizzati, soprattutto quando si lavora con codice e sistemi di progettazione di terze parti.

Immagine BEM di una scheda con i corsi
Un esempio illustrato di denominazione BEM da keepinguptodate.com.

I livelli a cascata mirano a risolvere questo problema. Introducono un nuovo livello a cascade CSS. Con gli stili a livelli, la precedenza di un livello supera sempre la specificità di un selettore.

Ad esempio, il selettore .post a.link ha una specificità maggiore rispetto a .card a. Se cerchi di applicare uno stile a un link, all'interno di una scheda o di un post vedrai che verrà applicato il selettore più specifico.

Utilizzando @layer, puoi essere più esplicito riguardo alla specificità di stile di ciascun link e assicurarti che gli stili del link della scheda prevalgano sugli stili del link del post, anche se la specificità potrebbe essere numericamente inferiore se tutto il tuo CSS si trovava sullo stesso piano. Questo è dovuto alla precedenza a cascata. Gli stili a livelli creano nuovi "piani" a cascata.

Illustrazione estratta dalla demo del progetto su come analizzare l'interfaccia utente

@layer in azione

Demo che mostra i colori dei link con le importazioni
Consulta la demo su Codepen.

Questo esempio mostra la potenza dei livelli a cascata, utilizzando @layer. Vengono visualizzati diversi link, alcuni senza nomi di classi aggiuntivi, uno con una classe .link e l'altro con una classe .pink. Il CSS aggiunge quindi tre livelli: base, typography e utilities nel seguente modo:

@layer base {
  a {
    font-weight: 800;
    color: red; /* ignored */
  }

  .link {
    color: blue; /* ignored */
  }
}

@layer typography {
  a {
    color: green; /* styles *all* links */
  }
}

@layer utilities {
  .pink {
    color: hotpink;  /* styles *all* .pink's */
  }
}

Fondamentalmente, tutti i link sono di colore verde o rosa. Il motivo è che, anche se .link ha una specificità a livello di selettore maggiore rispetto a a, esiste uno stile di colore su a con una precedenza più elevata (@layer). a { color: green } sostituisce .link { color: blue } quando la regola verde si trova in un livello dopo la regola blu.

La precedenza del livello supera la specificità dell'elemento.

Organizzazione dei livelli

Puoi organizzare i livelli direttamente nella pagina, come mostrato sopra, oppure nella parte superiore di un file.

L'ordine dei livelli viene stabilito a partire dalla prima volta che viene visualizzato il nome di ogni livello nel codice.

Ciò significa che se aggiungi quanto segue all'inizio del file, i link verranno visualizzati tutti in rosso, mentre il link con la classe .link diventerebbe blu:

@layer utilities, typography, base;

Questo avviene perché l'ordine dei livelli è ora invertito, mettendo le utilità all'inizio e alla base. Di conseguenza, le regole di stile nel livello base avranno sempre una specificità maggiore rispetto alle regole di stile nel livello Tipografia. I link non saranno più verdi, ma rossi o blu.

Screenshot del progetto Codepen
Consulta la demo su Codepen.

Organizzazione delle importazioni

Un altro modo per utilizzare @layer è importare i file. Puoi eseguire questa operazione direttamente durante l'importazione degli stili, utilizzando una funzione layer() come nell'esempio seguente:

/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */

/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */

/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */

Lo snippet di codice riportato sopra ha tre livelli: base, layouts e components. I file di normalizzazione, tema e tipografia in base, con un file post in layouts e cards e footer in components. Al momento dell'importazione del file, viene creata un'istanza dei livelli utilizzando la funzione livello. Un approccio alternativo consiste nell'organizzare i livelli nella parte superiore del file, dichiarandoli prima di qualsiasi importazione:

@layer base,
       theme,
       layouts,
       components,
       utilities;

L'ordine in cui @import i tuoi stili non è rilevante per l'ordine dei livelli, poiché è già stabilito alla prima istanza del nome del livello. Una cosa in meno di cui preoccuparsi. Puoi comunque impostare i file importati su livelli specifici, ma l'ordinamento è già stabilito.

Screenshot del progetto Codepen
Esplora il progetto su Codepen.

Livelli e cascata

Facciamo un passo indietro e vediamo dove vengono utilizzati i livelli in relazione alla cascata più ampia:

Illustrazione a cascata

L'ordine di precedenza è il seguente:

  • User agent normale (precedenza minima)
  • Utente locale @layer
  • Utente locale normale
  • Autore @layers
  • Autore normale
  • Autore !important
  • Autore @layer !important
  • Utente locale !important
  • User agent !important** (precedenza massima)

Potresti notare che gli stili @layer !important sono invertiti. Anziché essere meno specifici rispetto agli stili senza livelli (normali), hanno una precedenza più elevata. Questo è dovuto al modo in cui !important funziona nella cascata: interrompe la normale sequenza a cascata nei fogli di stile e inverte la normale specificità a livello di livello (precedenza).

Livelli nidificati

I livelli possono essere nidificati anche all'interno di altri livelli. L'esempio seguente è tratto dalla descrizione dei livelli Cascade di Miriam Suzanne:

@layer default {
  p { max-width: 70ch; }
}

@layer framework {
  @layer default {
    p { margin-block: 0.75em; }
  }

  p { margin-bottom: 1em; }
}

Nello snippet di codice riportato sopra, puoi accedere a framework.default utilizzando un . come indicatore del livello default nidificato all'interno di framework. Puoi anche scriverlo in un formato più breve:

@layer framework.default {
  p { margin-block: 0.75em }
}

I livelli e l'ordine dei livelli risultanti sono:

  • predefinito
  • framework.default
  • framework senza livelli
  • senza livelli

Aspetti a cui prestare attenzione

I livelli a cascata possono essere un'ottima soluzione se utilizzati correttamente, ma possono anche creare ulteriore confusione e risultati imprevisti. Quando lavori con i livelli a cascata, presta attenzione ai seguenti aspetti:

Regola 1: non utilizzare @layer per la definizione dell'ambito

I livelli a cascata non risolvono la definizione dell'ambito. Se hai un file CSS con @layer, ad esempio card.css e vuoi applicare uno stile a tutti i link all'interno della scheda, non scrivere stili come:

a {
  …
}

In questo modo, tutti i tag a del file riceveranno l'override. È comunque importante applicare l'ambito correttamente agli stili:

.card a {
  …
}

Regola 2: i livelli a cascata vengono ordinati dietro CSS senza livelli

È importante notare che un file CSS a più livelli non sostituisce il CSS senza livelli. Questa è stata una decisione intenzionale per semplificare l'introduzione di livelli in un modo più sensato per lavorare con il tuo codebase esistente. L'utilizzo di un file reset.css, ad esempio, è un buon punto di partenza e caso d'uso per i livelli a cascata.

Regola 3: !important inverte la specificità della cascata

Mentre gli stili con livelli sono meno specifici di quelli senza livelli in generale, l'uso di !important consente di annullare l'operazione. In un livello, le dichiarazioni con la regola !important sono più specifiche rispetto agli stili senza livelli.

In questo caso, gli stili !important invertono la loro specificità. Il diagramma qui sopra mostra a titolo di riferimento questo: autore @layers ha meno precedenza rispetto all'autore normale che ha meno precedenza rispetto all'autore !important, che ha meno precedenza rispetto all'autore @layer !important.

Se hai più livelli, il primo livello con !important avrà la precedenza !important e sarà lo stile più specifico.

Regola 4: comprendere i punti di inserimento

Poiché l'ordine dei livelli viene stabilito la prima volta che viene visualizzato il nome di ogni livello nel codice, se inserisci una dichiarazione @layer dopo aver importato e impostato layer() o dopo un'istruzione @layer diversa, è possibile ignorarla. A differenza dei CSS, dove per i livelli a cascata viene applicata la regola di stile più in basso nella pagina, l'ordine viene stabilito nella prima istanza.

Può essere in un elenco, in un blocco di livelli o in un'importazione. Se inserisci @layer dopo un elenco di importazione con layer(), non avverrà nulla. La sua posizione all'inizio del file imposterà l'ordine dei livelli e ti aiuterà a vedere chiaramente i livelli all'interno dell'architettura.

Regola 5: fai attenzione alla tua specificità

Con i livelli a cascata, un selettore meno specifico (come a) sovrascriverà un selettore più specifico (come .link) se questo selettore si trova su un livello più specifico. Considera quanto segue:

a in layer(components) sovrascriverebbe .pink in layer(utilities) se: @layer utilities, components è stato specificato. Sebbene si tratti di una parte intenzionale dell'API, ciò potrebbe creare confusione e frustrazione se non te lo aspettavi.

Quindi, se intendi scrivere classi di utilità, includile sempre in un livello di ordine superiore rispetto ai componenti con cui intendi sostituirle. Potresti pensare "Ho appena aggiunto questo corso .pink per cambiare il colore, ma non viene applicato".

Scopri di più sui livelli a cascata

Puoi anche consultare queste risorse per scoprire di più sui livelli a cascata: