Scivere CSS è facile ma non sempre si comportano come desiderato. In molti casi tutto si traduce in problemi di specificità e in questo articolo imparerai a gestirla come un professionista!
Quando si parla di CSS in molti storgono il naso, nonostante sia il linguaggio che permette di aggiungere stile alle nostre pagine, non è neanche un linguaggio di programmazione.
Oggi non parleremo di cosa sia un linguaggio di programmazione, quello che voglio fare è aiutarti a capire cosa sia la specificità dei CSS che, assieme al concetto di cascata, ci permettono di personalizzare le pagine web.
Leggendo questo articolo scoprirai quanto sia semplice calcolare la specificità e perché questa ti sarà utile per il tuo lavoro.
Ma se non sei ancora convinto, ecco qualche punto sul quale riflettere.
Perché imparare la specificità?
In molti pensano che comprendere la specificità non sia importante e non serve padroneggiarla fin dall’inizio, in fin dei conti basta aggiungere selettori alla regola CSS che stiamo scrivendo e il gioco è fatto.
Sbagliato!
Ritengo che la linea di pensiero “ci provo finché non trovo il selettore giusto” sia controproducente per diversi motivi.
Primo fra tutti, non tiene conto del fatto che noi possiamo pensare e ragionare su quanto stiamo facendo.
Lasciamo gran parte delle nostre scelte al motto: basta che funzioni.
Capisci perché certi stili non vengono applicati
Comprendere la specificità delle regole che utilizziamo permette di debuggare più velocemente il codice e scoprire prima come risolvere la situazione.
In questi casi anche avere un browser con buoni strumenti di sviluppo aiuta, non per niente su SkillsAndMore consigliamo da sempre Firefox Developer Edition, ma il nostro cervello è più veloce di qualsiasi strumento.
Quindi la prossima volta che il tuo CSS non si comporta come desideri, al posto di schiaffare un !important
su quella proprietà potresti accendere il cervello e sfruttare le tue conoscenze sulla specificità per risolvere il problema.
Fidati, il tuo Io futuro te ti ringrazierà per usare la specificità ?
Organizzi meglio il tuo codice CSS
Usare !important
è sbagliato non soltanto perché stai sovrascrivendo in maniera forzata la proprietà applicata all’elemento ma anche perchè così facendo stai distruggendo la logica del tuo foglio di stile.
Rischi di far morire una fatina!
Ricordo che in aula durante una lezione ho usato l’espressione: “Ogni volta che usi !important
muore una fatina.”. Il mio tentativo è farti ricordare quanto questa pratica sia sbagliata e spero che con questa frase il concetto resti bene a mente, come fu per i miei studenti.
In molti sviuppatori hanno cercato di migliorare l’organizzazione del nostro codice proponendo strutture e nomi da usare nei fogli di stile, l’approccio Block-Element-Modifier (BEM) è uno dei più diffusi.
La verità è che con una volta compresa la specificità potrai scrivere fogli di stile organizzati senza neanche dover ricorrere a questi approcci!
Scrivi meno codice e lavora velocemente
Come si suol dire “Il tempo è denaro” e per questo torno a consigliarti di comprendere cosa sia e come funziona la specificità CSS.
Padroneggiare i suoi concetti ti permetterà di identificare prima il selettore ideale da utilizzare e procedere rapidamente alla conclusione del progetto.
Comprendi la specificità
Ti ho parlato fino a ora del perché dovresti conoscere la specificità e magari hai anche compreso la sua importanza nella scrittura dei fogli di stile ma forse non ho introdotto bene l’argomento.
Sai che cosa è la specificità dei CSS?
Detto in parole povere calcolare la specificità di un selettore ci permette di capire quali sono le regole che andranno a sovrascrivere quelle già dichiarate.
Saprai in un baleno se le nuove regole che stai inserendo verranno applicate perché utilizzerai il selettore giusto, quello più specifico.
Nel prossimo esempio trovi un CodePen dove è presente un div
con classe box
, sapresti dirmi perché ha uno sfondo rosso (dichiarato con il selettore .box
) e non blue (dichiarato con il selettore div
)?
Questo è un esempio classico di specificità perché dimostra chiaramente che un selettore può sovrascrivere le regole dichiarate in un altro.
Controllando il codice avrai notato che .box
è stato dichiarato dopo div
e quindi potresti pensare che non si tratti di specificità ma della classica cascata CSS.
Questo sarebbe stato vero se fosse stato usato lo stesso selettore, stesso selettore stessa specificità.
Qua non stiamo parlando di cascata però perché il browser ritiene il selettore .box
più importante (specifico) di div
.
Come è arrivato a questa conclusione?
Certo, con un esempio semplice come questo anche noi riusciamo a capire che div
è un selettore più generico rispetto a .box
. Con il primo selezioniamo qualsiasi div
presente nella pagina mentre con il secondo soltanto gli elementi che presentano una specifica classe.
Però il browser non pensa in questo modo, non può affidarsi alla logica perché ha bisogno di svolgere dei calcoli e prendere decisioni basandosi su formule matematiche.
Per questo si parla di calcolare la specificità di un selettore.
La specificità non è altro che una serie numerica che permette ai browser di capire quale regola CSS prenderà il sopravvento sulle altre che cercano di selezionare lo stesso elemento.
I principali gruppi di specificità
Ho appena parlato di serie numerica che ci aiuta a comprendere la specificità dei CSS ma prima di conoscerla nel dettaglio hai bisogno di scoprire i gruppi di selettori che creano questa serie.
Ormai dovrebbe essere chiaro, ogni selettore CSS ha una certa importanza (specificità) agli occhi di un browser ma in linea generale possiamo raggruppare i selettori nel seguente modo.
Selettore ID
/* Seletore ID */ #id { ... }
Il selettore più potente di tutti.
Usare ID nei tuoi CSS ti permette di sovrascrivere qualsiasi altra regola che viene applicata sull’elemento da altri selettori.
Selettore classe, attributi o pseudo classi
Subito sotto troviamo un gruppo di selettori che se la giocano.
Sono meno importanti del precedente ID ma sono comunque considerati più importanti dei successivi.
/* Seletore Classe */ .box { ... } /* Seletore Attributo */ [type="submit"] { ... } /* Pseudo Classe */ :hover { ... }
L’ID è un selettore che deve selezionare un unico elemento, per questo è in grado di vincere su questo altro gruppo. Con questi selettori si identifica un gruppo di elementi che condividono una specifica caratteristica, sia questa la presenza di una classe, di un attributo o una pseudo-classe.
Selettore tipo e pseudo elementi
Ultimi nella classifica dei gruppi di specificità troviamo i selettori di tipo e gli pseudo elementi.
/* Seletore Tipo */ div { ... } /* Pseudo Elemento */ ::before { ... }
Questi sono dei selettori ancora più generici rispetto ai precedenti perché non vanno a cercare delle caratteristiche comuni, semplicemente cercano di individuare uno specifico tipo di elemento.
Eccezioni che ti faranno grattare la testa
Per ogni regola esistono delle eccezioni. Secondo lo schema precedente un ID sovrascrive le proprietà impostate da una classe e quest’ultima sovrascrive quelle impostate da un selettore tipo. Però non sempre questo è il caso.
Ci sono alcune eccezioni a questo raggruppamento che potrebbero farti perdere del tempo:
- il selettore universale (
*
), i combinatori (>
,+
, …) e la pseudo classe di negazione (:not()
) non hanno alcun effetto sulla specificità, - gli stili in linea (quelli dichiarati in un elemento HTML con l’attributo
style
) sovrascrivono sempre le proprietà dichiarate all’interno di fogli di stile esterni, !important
sovrascrive le proprietà dichiarate in altre regole ingnorandone la specificità, come già descritto questa è una pratica veramente sconsigliata (pensa alle fatine).
Descritte le eccezioni è giunto il momento di scoprire come calcolare la specificità.
Impara a calcolare la specificità
Ho desiderato introdurti prima i gruppi di selettori perché, come anticipato, questi definiscono la serie numerica che il browser calcola per comprendere quale valore applicare della proprietà definita in diverse regole CSS che selezionano lo stesso elemento.
Continuo a parlare di serie numerica perché la specificità non si presenta come un unico numero, anche se lo sembra. La specificità si basa sui gruppi evidenziati prima per creare quattro numeri che identificano la specificità.
Ecco svelato il risultato che si ottiene una volta calcolata la specificità di un selettore. Guardiamo adesso come il browser calcola questi valori nella forma più semplice.
Attributo style
Se un elemento HTML ha un attributo style
le proprietà CSS al suo interno sovrascrivono i valori dichiarati all’interno dei fogli di stile.
<a href="#" style="color: red">Cliccami</a>
ID
Per ogni ID che viene specificato in una regola CSS si aggiunge 1 al gruppo relativo agli ID.
#id { ... }
Nel prossimo esempio trovi una situazione che raramente dovresti incontrare perché da definizione gli ID sono selettori che permettono di identificare univocamente un elemento presente nella pagina e in teoria non servono più ID nello stesso selettore ma mi è comodo per farti capire meglio come viene calcolata la specificità.
#primo-id #secondo-id #terzo-id { ... }
Ricordando che il calcolo della specificità aggiunge 1 per ogni ID presente nel selettore, quando dovrebbe essere il calcolo della specificità in questo caso?
La cifra che identifica i selettori diventa 3 perché tre sono gli ID utilizzati nel selettore precedente.
Classi, attributi e pseudo-classi
Come successo per i precedenti anche in questo caso viene aggiunto un 1 alla cifra che identifica questo gruppo di selettori.
.classe { ... }
Proprio come successo precedentemente potresti usare un numero maggiore di selettori dello stesso tipo, per esempio:
.classe[type="text"]:hover { ... }
Questo è un esempio veramente estremo ma il calcolo della specificità sarebbe:
.prima-classe .seconda-classe .terza-classe { ... }
Questo potrebbe sembrare un selettore completamente diverso dal precedente ma se andiamo a calcolarne la specificità scopriremo che ha lo stesso identico valore:
Tipo e pseudo-elemento
Continuando con la carrellata dei selettori andiamo a scoprire adesso quello che vale meno di tutti:
p { ... }
Il selettore tipo o quelli per gli pseudo-elementi sono i più deboli perché se andiamo a calcolarne la specificità possiamo scoprire che questi vanno a popolare l’ultima cifra, quella relativa ai selettori con una specificità basse.
Calcolare la specificità CSS
A questo punto dovresti avere le idee abbastanza chiare.
Ogni regola CSS ha una sua importanza (specificità) che il browser calcola per scegliere il valore da applicare a una precisa proprietà di un elemento.
Negli esempi precedenti ti ho mostrato come calcolare la specificità quando è presente un unico selettore e anche se più avanti ti presenterò qualche risorsa per aiutarti in questo compito voglio approfondire aggiungendo qualche esempio più complesso.
Ecco mostrato come pensa un browser quando calcola la specificità di una regola CSS, come detto in precedenza prende in considerazione ogni singolo selettore presente per poi generare un unico insieme di cifre che rappresenta l’importanza di una regola.
Alla fine si tratta soltanto di aritmetica, solo addizione.
Torniamo adesso all’esempio principale di questo articolo dove abbiamo scoperto che le regole impostate con il selettore .box
hanno una specificità maggiore rispetto a quelle dichiarate con div
.
Ora che abbiamo fatto questa lunga presentazione, sapresti dirmi perché avviene questo?
Ancora troppo presto?
Nessun problema ecco spiegato come mai succede:
Il secondo selettore (.box
) è più importante perché ha una specificità più alta, entrambe hanno un valore di 1 ma .box
vince perché il suo valore è impostato in un gruppo che ha una specificità più alta.
Confuso?
Prova a guardare nuovamente l’immagine che ho creato per riassumere il calcolo della specificità.
A sinistra troviamo una specificità più alta, rappresentata dalla presenza di attributi style
, per andare man mano a gruppi che hanno una specificità più bassa.
Quando il browser calcola la specificità di una regola CSS non tiene conto soltanto dei valori dei singoli selettori ma anche la loro posizione, o per dirla in un altro modo il gruppo di selettori di cui fanno parte.
Vediamo un po’ se adesso ti è più chiaro. Chi vince tra le seguenti regole?
A prima vista potrebbe sembrare che siano le classi a vincere, in fin dei conti sono 3 e l’ID, anche se importante, è soltanto 1.
Ma sbaglieresti.
La specificità di un ID è sempre maggiore rispetto agli altri raggruppamenti, non importa quanti selettori hai inserito. Dato che il selettore ID si trova in un gruppo con specificità più alta, anche se minore, sovrascriverà sempre le regole dichiarate con gruppi di selettori con specificità più bassa.
Facciamo un altro esempio.
Anche in questo caso, da una parte abbiamo un singolo selettore mentre dall’altra ne abbiamo tre dello stesso livello.
Se hai compreso la direzione che segue il browser per identificare la regola CSS più specifica avrai già capito che vince nuovamente la regola a sinistra. In fin dei conti i selettori di tipo classe sono in un gruppo più specifico rispetto a quello dei selettori tipo e pseudo-elemento.
Però basterebbe aggiungere una singola classe per ribaltare la situazione:
Dato che il valore nel gruppo dei selettori delle classi è lo stesso, il browser passa ad analizzare il gruppo successivo e dato che nell’esempio di destra troviamo un valore di tre saranno le proprietà dichiarate al suo interno ad essere applicate.
Strumenti utili per il calcolo della specificità CSS
Spero che adesso per te sia più semplice comprendere la specificità dei selettori CSS e che d’ora in poi possa apprezzare i vantaggi che la sua conoscenza porterà nel tuo lavoro.
La cosa bella è che non sei costretto a fare tutto da solo.
In molti hanno cercato di rendere più semplice la comprensione della specificità CSS, alcuni hanno anche creato delle infografiche! La più divertente e chiara per noi appassionati di fantascienza è quella che la rappresenta sfruttando i personaggi di Star Wars:
Prima di salutarti però voglio lasciarti con altri due strumenti che puoi usare per migliorare ulteriormente la tua comprensione della specificità CSS.
Il primo è un sito web che permette di calcolare la specificità delle regole CSS che inseriamo al suo interno. Si chiama Specificity Calculator e si presenta in questo modo:
Basta inserire i selettori che desideri confrontare e premere sul pulsante Sort by specificity e posizionato in alto troverai il selettore più specifico.
Altro strumento utile potrebbe essere il tuo stesso editor di codice.
Ultimamente sto lavorando molto, quasi esclusivamente, con VS Code perché lo ritengo la perfetta unione tra un semplice editor di codice e un potente IDE.
Ma non te lo presento perché è il miglior editor di codice al mondo, lo sto facendo perché per quello che so è l’unico editor che ti mostra la specificità di una regola CSS facendo hover sul selettore.
Oltre alla specificità della regola CSS hai anche una preview dell’HTML che verrà selezionato, mica male ?
Conclusioni
E così sei giunto al termine di questo articolo, che ne pensi?
Sfrutterai i concetti appresi nel tuo lavoro di sviluppatore web?
Se vuoi congratularti con me (o criticarmi) per l’articolo che hai appena letto puoi farlo pubblicamente lasciando un tuo commento o condividendo l’articolo con i tuoi amici e colleghi.
La condivisione ci aiuterà a far conoscere i nostri contenuti ma tu avrai la nostra eterna gratitudine!
Anna dice
Se volessi sovrascrivere un elemento (proviene da un tema quindi vorrei evitare di andare a toccare il style.css originale) a cui è stato applicato !important cosa devo fare?
Andrea Barghigiani dice
Ciao Anna, a mio avviso chi ha sviluppato il tema non conosceva bene la specificità e probabilmente non è l’unico dei problemi che presenta.
Se ti trovi nella situazione di non poter cambiare tema potresti provare una delle seguenti soluzioni:
In entrambi i casi, purtroppo, dovrai trovare un selettore più specifico di quello usato nel tema che stai utilizzando e utilizzare anche
!important
per assicurarti di sovrascrivere il valore inserito.Spero di averti aiutata a trovare una soluzione.