I livelli in cascata (la @layer
regola CSS) saranno disponibili in Chromium 99, Firefox 97 e Safari 15.4 beta. Consentono un controllo più esplicito dei file CSS per evitare conflitti di specificità degli stili. Questo è particolarmente utile per codebase di grandi dimensioni, sistemi di progettazione e per la gestione di stili di terze parti nelle applicazioni.
La stratificazione del CSS in modo chiaro impedisce l'override di stili inaspettato e favorisce una migliore architettura CSS.
Specificità CSS e gerarchia
La specificità CSS indica in che modo il CSS decide quali stili applicare a quali 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. Si tratta di un aspetto fondamentale dell'apprendimento del CSS.
Le persone ricorrono a convenzioni di denominazione CSS come BEM per evitare di eseguire l'override della specificità in modo involontario. Se assegni a tutto un'unica classe, tutto viene inserito nello stesso piano di specificità. Tuttavia, non è sempre possibile mantenere stili così organizzati, soprattutto quando si utilizzano sistemi di design e codice di terze parti.
Lo scopo dei livelli a cascata è risolvere questo problema. Introducono un nuovo livello alla cascata 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 di .card a
. Se stai cercando di applicare uno stile a un link all'interno di una scheda in un post, verrà applicato il selettore più specifico.
Utilizzando @layer
, puoi specificare in modo più esplicito la specificità dello stile di ciascuno e assicurarti che gli stili del link della scheda sostituiscano quelli del link del post, anche se la specificità potrebbe essere numericamente inferiore se tutti i CSS fossero sullo stesso piano. Questo accade a causa della precedenza in cascata. Gli stili a livelli creano nuovi "piani" in cascata.
@layer
in azione
Questo esempio mostra la potenza dei livelli in cascata, utilizzando @layer
. Vengono visualizzati diversi link: alcuni senza nomi di classi aggiuntivi, uno con una classe .link
e uno con una classe .pink
. Il CSS aggiunge quindi tre livelli: base
, typography
e utilities
come segue:
@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 */
}
}
Alla fine, tutti i link sono verdi o rosa. Questo perché, sebbene .link
abbia una specificità a livello di selettore superiore a a
, a
ha uno stile di colore in @layer
con una precedenza più alta. a { color: green }
sostituisce .link { color: blue }
quando la regola verde si trova in un livello successivo alla regola blu.
La precedenza del livello ha la precedenza sulla specificità dell'elemento.
Organizzare i livelli
Puoi organizzare i livelli direttamente nella pagina, come mostrato sopra, oppure nella parte superiore di un file.
L'ordine dei livelli viene stabilito la prima volta che il nome di ogni livello viene visualizzato nel codice.
Ciò significa che, se aggiungi quanto segue all'inizio del file, tutti i link verranno visualizzati in rosso, mentre il link con la classe .link
verrà visualizzato in blu:
@layer utilities, typography, base;
Questo perché l'ordine dei livelli è ora invertito, con le utilità prima e la base per ultima. Di conseguenza, le regole di stile nel livello base
avranno sempre una specificità maggiore rispetto alle regole di stile nel livello di tipografia. Non saranno più link verdi, ma rossi o blu.
Organizzazione delle importazioni
Un altro modo per utilizzare @layer
è con i file di importazione. Puoi farlo direttamente quando importi gli 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
, un file post
in layouts
e cards
e footer
entrambi in components
. Al momento dell'importazione del file, gli strati vengono istantaneamente creati utilizzando la funzione layer. Un approccio alternativo consiste nell'organizzare i livelli nella parte superiore del file, dichiarandoli prima di qualsiasi importazione:
@layer base,
theme,
layouts,
components,
utilities;
Ora l'ordine in cui @import
gli stili non ha più importanza per l'ordine dei livelli, poiché è già stabilito alla prima istanza del nome del livello. Una preoccupazione in meno. Puoi comunque impostare i file importati su livelli specifici, ma l'ordine è già stabilito.
Livelli e struttura a cascata
Facciamo un passo indietro e vediamo dove vengono utilizzati i livelli rispetto alla struttura a cascata più ampia:
L'ordine di precedenza è il seguente:
- User agent normale (priorità più bassa)
- Utente locale @livello
- Utente locale normale
- Autore @layers
- Autore normale
- Autore !important
- Author @layer !important
- Utente locale !important
- User Agent !important** (priorità massima)
Potresti notare che gli stili @layer !important
sono invertiti. Invece di essere meno specifici degli stili non a livelli (normali), hanno una priorità maggiore. Questo è dovuto al funzionamento di !important
nella struttura a cascata: interrompe la normale applicazione a cascata degli stili e inverte la normale specificità a livello di livello (precedenza).
Livelli nidificati
I livelli possono anche essere nidificati all'interno di altri livelli. L'esempio seguente è tratto dalla spiegazione dei livelli a cascata 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 in framework
. Puoi anche scrivere questa espressione in un formato più abbreviato:
@layer framework.default {
p { margin-block: 0.75em }
}
I livelli e l'ordine risultanti sono:
- predefinita
framework.default
framework
senza livelli- senza livelli
Aspetti a cui prestare attenzione
I livelli in cascata possono essere molto utili se li utilizzi correttamente, ma possono anche creare ulteriore confusione e risultati inaspettati. Quando utilizzi gli strati a cascata, tieni presente quanto segue:
Regola 1: non utilizzare @layer
per l'ambito
I livelli a cascata non risolvono il problema dell'ambito. Se hai un file CSS con un @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
nel file verranno sostituiti. È comunque importante definire l'ambito degli stili in modo appropriato:
.card a {
…
}
Regola 2: i livelli in cascata sono ordinati dietro il CSS non a livelli
È importante notare che un file CSS a livelli non sostituirà il CSS non a livelli. Si è trattato di una decisione intenzionale per semplificare l'introduzione dei livelli in un modo più sensato per lavorare con la base di codice esistente. L'utilizzo di un file reset.css
, ad esempio, è un buon punto di partenza e un caso d'uso per i livelli a cascata.
Regola 3: !important
inverte la specificità della cascata
Sebbene in generale gli stili a livelli siano meno specifici di quelli non a livelli, l'utilizzo di !important
inverte questa situazione. In un livello, le dichiarazioni con la regola !important
sono più specifiche rispetto agli stili non a livelli.
In questo caso, gli stili !important
invertono la loro specificità. Il diagramma riportato sopra mostra questo come riferimento: author @layers ha una precedenza inferiore rispetto ad author normal, che ha una precedenza inferiore rispetto ad author !important, che ha una precedenza inferiore rispetto ad author @layer !important.
Se hai più livelli, il primo livello con !important
avrà la precedenza su !important
e sarà lo stile più specifico.
Regola 4: comprendi i punti di inserimento
Poiché l'ordine degli strati viene stabilito la prima volta che il nome di ogni livello viene visualizzato nel codice, se inserisci una dichiarazione @layer
dopo aver importato e impostato i layer()
o dopo un'istruzione @layer
diversa, questa può essere ignorata. A differenza del CSS, in cui la regola di stile più in basso nella pagina viene applicata per i livelli a cascata, l'ordine viene stabilito alla prima occorrenza.
Può trovarsi in un elenco, in un blocco di livello o in un'importazione. Se inserisci @layer
dopo un elenco di importazione con layer()
, non succederà nulla. Se lo inserisci nella parte superiore del file, imposterai l'ordine dei livelli e potrai vedere chiaramente i livelli all'interno dell'architettura.
Regola 5: fai attenzione alla specificità
Con i livelli in cascata, un selettore meno specifico (ad es. a
) sostituirà un selettore più specifico (ad es. .link
) se si trova in un livello più specifico. Considera quanto segue:
a
in layer(components)
sostituirà .pink
in layer(utilities)
se: è stato specificato @layer utilities, components
. Sebbene sia una parte intenzionale dell'API, potrebbe essere fonte di confusione e frustrazione se non te lo aspetti.
Pertanto, se scrivi classi di utilità, includile sempre come livello di ordine superiore rispetto ai componenti con cui intendi sostituirle. Potresti pensare: "Ho appena aggiunto questa classe .pink
per cambiare il colore, ma non viene applicata".
Scopri di più sui livelli in cascata
Per saperne di più sui livelli in cascata, puoi anche consultare queste risorse: