css Advanced 4 min

Cascade Layers: gestire la specificità nei progetti grandi

@layer order, reordering, layer anonimi e !important dentro i layer

· 824 parole

Nella pillola sulla cascade abbiamo incontrato @layer. Qui lo guardiamo da vicino, perché è lo strumento pensato apposta per un problema molto concreto nei progetti grandi: la «guerra di specificità» quando per battere uno stile di un framework o di codice legacy finisci per scrivere selettori sempre più contorti, o peggio, usiamo !important ovunque.

In un cantiere lavorano più squadre: muratori, elettricisti, imbianchini, senza un ordine di intervento stabilito. I cascade layer sono il capocantiere che stabilisce l'ordine: prima i muratori, poi gli elettricisti, poi gli imbianchini.

1. @layer order: l'ordine di dichiarazione decide tutto

La regola è semplice quanto assoluta: il primo layer dichiarato ha la priorità più bassa, l'ultimo la più alta. Non conta quanto sia specifico un selettore al suo interno, conta solo la posizione del layer nell'ordine dichiarato.

@layer reset, base, componenti, utility; 
@layer reset { * 
   { 
   margin: 0; 
   padding: 0; 
   } 
} 
@layer base { 
   body { 
   font-size: 16px; 
   } 
} 
@layer componenti { 
   .btn { 
    background: gray; 
    } 
} 
@layer utility { 
   .btn { 
   background: purple; 
   } 
} /* vince: e' l'ultimo layer */

Nota il primo rigo: @layer reset, base, componenti, utility; senza parentesi è una dichiarazione (statement), non un blocco di stili. Serve solo a fissare l'ordine in anticipo, anche prima di scrivere una sola riga di CSS in quei layer.

Fonte: MDN Web Docs: «@layer»: il primo layer dichiarato ha la priorità più bassa, l'ultimo la più alta.

2. Reordering: perché conviene dichiarare l'ordine subito

Un layer, una volta creato con un certo nome, non cambia più posizione: la sua priorità resta quella del primo momento in cui è stato dichiarato, non dell'ultimo. Questo significa che puoi pre-registrare tutto l'ordine a inizio foglio con una singola dichiarazione, e poi riempire i layer via via, anche in punti diversi del file o in file diversi, l'ordine resta quello fissato all'inizio.

@layer base, layout, componenti; /* ordine deciso qui, una volta per tutte */ 
/* piu' avanti nel file, o in un altro file importato... */ 

@layer componenti { 
   .card { 
    border-radius: 8px; 
   } 
} 
@layer base { 
   body { 
   color: #222; 
   } 
} 
/* l'ordine resta base -> layout -> componenti, a prescindere da dove scrivi cosa */

Come pubblicare in anticipo il programma di una conferenza: «mattina: apertura, poi workshop, poi chiusura», anche prima di sapere esattamente cosa dirà ogni relatore. L'ordine delle sessioni è fissato; i contenuti si aggiungono dopo, senza scombinare la scaletta.

3. Layer anonimi: utili, ma con dei limiti

Puoi creare un layer senza nome con @layer { ... }. È un layer anonimo: conta comunque nell'ordine generale (in base a quando viene dichiarato), ma con due limiti importanti: è unico e non essendo referenziabile per nome, non puoi più aggiungergli stili altrove nel foglio.

@layer { 
   .avviso { 
    color: crimson; 
    } 
} 
/* layer anonimo: chiuso per sempre */ 

@layer { 
   .avviso { 
     color: teal; 
   } 
} /* un ALTRO layer anonimo, diverso dal primo */

Utili per un piccolo blocco isolato di stili (un «reset minimo», per esempio) che sai già non dovrai mai più toccare o riordinare. Per tutto il resto, meglio i layer nominati: puoi tornarci ed espanderli quando vuoi.

4. !important nei layer: l'ordine si ribalta

Ecco il colpo di scena che sorprende quasi tutti la prima volta: dentro i layer, !important inverte l'ordine di priorità. Tra due regole !important in layer diversi, vince quella nel layer dichiarato per primo: l'esatto contrario di quanto succede con le regole normali.

@layer base, utility; 
@layer base { 
   .btn { 
     background: gray !important; 
   } 
} 
/* VINCE */ 

@layer utility { 
   .btn { 
     background: purple !important; 
    } 
} /* perde, pur essendo l'ultimo layer */

Perché questa apparente contraddizione? Perché !important segnala «questa regola è così critica che deve resistere a qualunque sovrascrittura successiva» e in un sistema a strati, «resistere a ciò che viene dopo» significa proprio dare precedenza a chi lo dichiara per primo. MDN nota che questa logica è coerente con lo stesso principio che regola !important tra le origini (browser/utente/autore).

In una catena di comando, un ordine urgente («!important») dato dal primo superiore non può essere cancellato da un ordine urgente successivo di un altro superiore di pari grado: chi ha lanciato l'allarme per primo mantiene la priorità, proprio perché l'urgenza è pensata per non essere scavalcata.

Da ricordare che gli stili fuori da ogni layer battono sempre quelli dentro i layer (nelle regole normali), ma perdono contro un !important scritto dentro un layer qualsiasi.

Fonte: MDN Web Docs: «@layer» e «Introduction to the CSS cascade»: !important inverte l'ordine di priorità dei layer.

In sintesi

Regola Cosa significa Esempio
Ordine layer Primo dichiarato = priorità più bassa @layer a, b, c;
Dichiarazione anticipata L'ordine si fissa alla prima dichiarazione, non cambia più @layer a, b, c; (statement)
Layer anonimo Unico, non richiamabile per nome, non estendibile @layer { ... }
!important nei layer Inverte l'ordine: il primo layer vince @layer a { x!important } vince su b
Non-layered Batte i layer normali, perde contro !important nei layer stile fuori da ogni @layer

I cascade layer non sostituiscono la specificità: le si mettono sopra, come un livello di controllo più alto e dichiarato esplicitamente da chi scrive il CSS, invece che dedotto dai selettori. In un progetto grande, questo significa poter dire una volta per tutte «prima il framework, poi il mio codice» e non doverlo più ripetere selettore per selettore.

@layer
Accedi o registrati per votare, salvare o commentare la pillola

Commenti (0)

Registrati per commentare, fare domande e proporre l'argomento della prossima pillola (oppure accedi se hai già un account).

Nessun commento. Sii il primo a scrivere qualcosa.

Pillole correlate