Se non conosci ancora la famiglia di pseudo-classi nth-*
questa è la tua occasione per imparare tutto quello che c’è da sapere e migliorare le tue conoscenze CSS.
Selezionare con precisione gli elementi di una pagina web è un’attività fondamentale, spesso questi vengono selezionati con ID o classi ma è giunto il momento di scoprire un metodo avanzato per selezionarli in base alla loro posizione.
Parlo di metodo avanzato perché quello che stiamo per scoprire è una funzionalità dei CSS abbastanza “nascosta” e che non tutti sanno padroneggiare completamente.
Utilizzarla nel modo corretto però ti aiuterà velocizzare il tuo lavoro senza dover trovare complicati modi per modificare l’HTML.
Perché usare le pseudo-classi nth-*
?
Già, perché mai investire il tuo tempo per imparare qualcosa di nuovo su un linguaggio che usi praticamente tutti i giorni?
La risposta semplice è: ti semplificherai la vita.
Se vogliamo invece analizzare gli aspetti interessanti e le motivazioni per le quali dovresti imparare a usare queste strutture (e che in tutta onestà mi spingono a scrivere questo articolo) posso riassumerle di seguito.
Non dovrai modificare l’HTML
Lavorare con ID e classi è sicuramente comodo e attraverso la specificità dei selettori possiamo selezionare qualsiasi elemento presente in una pagina web ma non sempre possiamo modificare il codice HTML per aggiungere questi attributi.
Per esempio in WordPress esistono moltissimi plugin, widget e blocchi che generano delle liste non ordinate prendendo dinamicamente il contenuto da mostrare.
Utilizzando il blocco widget Categorie questo è il risultato che ottengo:
Anche se il blocco (o la widget) offre delle opzioni per personalizzare il contenuto presentato non ho alcun modo per selezionare correttamente il quinto elemento della lista!
Se si avesse il controllo del codice HTML generato potrei aggiungere una classe al quinto elemento e personalizzarlo il questo modo ma in un contesto del genere non posso agire direttamente sulla struttura del documento.
Imparando a utilizzare nth-child()
e le altre pseudo classi potrai facilmente selezionare i tuoi elementi direttamente dal CSS.
Seleziona in base alla posizione
Estendendo il punto precedente un altro valido motivo per imparare a utilizzare queste pseudo classi è dettato dal fatto che oltre a non dover modificare la struttura potrai selezionare gli elementi in base alla loro posizione.
La selezione del quinto elemento era soltanto un esempio, immagina un attimo di dover selezionare tutti gli elementi pari di una lista.
Senza conoscere le nth-*
dovresti aggiungere una classe ad ogni elemento ma ti basterebbe conoscere una sola di queste pseudo classi per risolvere tutto con una singola riga di CSS.
Già con la cascata dei CSS e ad alcuni selettori particolari come il child combinator o il general sibling è possibile selezionare i nostri elementi in base alla loro posizione ma sarai comunque molto limitato.
Manterrai una struttura più pulita
Negli ultimi anni ho notato che molti framework frontend si stanno abbandonando all’idea di realizzare una serie di classi CSS per applicare determinati stili in un documento.
Non è raro infatti trovare in framework come Bootstrap o Tailwind CSS i nostri elementi HTML arricchiti di classi come btn btn-primary my-2
oppure py-12 px-4 text-center
.
A parte le classi btn
e btn-primary
tutte le altre sono classi che vanno a richiamare singole regole CSS che applicano padding
, margin
e text-align
.
Anche se molti sviluppatori apprezzano questo modo di lavorare quando lavoriamo con CMS che non sempre ci permettono di gestire il codice HTML generato personalmente lo trovo controintuitivo.
Utilizzando questi framework dovrei modificare il mio HTML ogni volta che desidero personalizzare un elemento senza poter fare leva su le caratteristiche più avanzate e potenti del CSS.
Invece continuando a leggere questo articolo imparerai come non dipendere da ID e classi per personalizzare i tuoi elementi.
nth-child()
la tua prima pseudo classe
Iniziamo quindi ad entrare nel vivo dell’articolo e cerchiamo di capire meglio come funzionano queste pseudo-classi.
La prima che ti voglio presentare è nth-child()
grazie alla quale posso introdurti la loro logica di base ma non ti preoccupare, potrai già fare moltissimo con questa!
Iniziamo condividento il codice HTML che utilizzeremo come base per tutti i prossimi esempi:
<ul> <li><a href="#">Blogging</a></li> <li><a href="#">Carriera</a></li> <li><a href="#">CSS</a></li> <li><a href="#">HTML</a></li> <li><a href="#">JavaScript</a></li> <li><a href="#">Marketing</a></li> <li><a href="#">News</a></li> <li><a href="#">WordPress</a></li> <li><a href="#">Workflow</a></li> </ul>
Se vuoi sperimentare tu stesso con questo codice ho preparato un CodePen per te contenente tutte le prove che vedrai in questo articolo, forkalo e fai i tuoi esperimenti!
Riprendiamo adesso l’esempio precedente, come puoi selezionare il quinto elemento senza modificare il codice HTML?
Ovviamente questa è una domanda retorica perché la risposta è: utilizzando nth-child()
, ma come?
Ti ho presentato questa pseudo-classe con le parentesi tonde perché questo è un tipo di selettore particolare dei CSS, praticamente ci permette di passare dei parametri per specificare ulteriormente la nostra selezione.
Ecco come andare a selezionare il quinto li
:
li:nth-child(5){ /* Regole CSS */ }
Passando la posizione dell’elemento che vuoi selezionare come parametro numerico di nth-child()
puoi personalizzarlo facilmente con tutto il codice CSS di cui hai bisogno.
Ricorda che stiamo usando pseudo-classi
Non ti dimenticare che stiamo usando delle pseudo-classi e come tali è fondamentale specificare l’elemento di partenza e utilizzare i due punti (:
) durante la loro dichiarazione.
Utilizzando un valore numerico possiamo specificare la posizione di un singolo elemento, già questo è un aspetto molto utile che ci permette di aggiungere stile alle nostre pagine senza dover modificare la struttura.
Ma è possibile che nth-child()
sia utile soltanto per la selezione di un singolo elemento?
Assolutamente no! nth-child()
è una pseudo-classe molto più potente!
Seleziona tutti gli elementi pari (o dispari)
Continuiamo con i vari esperimenti e a questo punto dell’articolo voglio rispondere alla seconda domanda che ti avevo posto precedentemente: come possiamo selezionare tutti gli elementi pari di una lista?
Per fare una selezione di questo tipo devo presentarti un’altra caratteristica di nth-child()
riguardante i parametri che accetta all’interno delle parentesi tonde.
Puoi passare testo o espressioni come parametri di nth-child()
.
Adesso che sai che i valori numerici non sono gli unici parametri che puoi passare concentriamoci momentaneamente sul testo che possiamo fornire, le espressioni le affronteremo nella prossima sezione.
Abbiamo detto che desidero selezionare tutti gli elementi pari della lista giusto? Ebbene ecco la singola riga di codice CSS che ti avevo promesso:
li:nth-child(even){ /* Regole CSS */ }
Passando even
come parametro di nth-child()
stiamo dicendo al browser di selezionare tutti i li
pari che sono contenuti nello stesso contenitore.
Se sei invece interessato a selezionare tutti gli elementi dispari non dovrai far altro che sostituire even
con odd
e il gioco è fatto. Grazie a un singolo selettore hai creato un effetto zebra per le tue liste o tabelle!
Utilizziamo le espressioni
Fino ad ora abbiamo visto che nth-child()
accetta come parametro un valore numerico, con il quale seleziona un singolo elemento, oppure un valore testuale, che gli permette di selezionare gli elementi pari o dispari.
Però questa pseudo-classe è ancora più potente degli esempi mostrati e grazie alle espressioni ci permette di selezionare ogni terzo elemento, ogni quarto elemento partendo dal primo e qualsiasi altro tipo di ritmo desideri implementare.
La stessa selezione di elementi pari (o dispari) può essere tradotta con un’espressione.
/* Seleziono elementi pari con testo */ li:nth-child(even){ /* Regole CSS */ } /* Seleziono elementi pari con espressione */ li:nth-child(2n){ /* Regole CSS */ }
Come hai potuto scoprire con i tuoi occhi utilizzando l’espressione 2n
andiamo a selezionare tutti gli elementi pari senza dover utilizzare la parola chiave even
.
Questo apre le porte al concetto di espressione all’interno della pseudo-classe nth-child()
, quella che vedi al momento è la sua forma più semplice dove stiamo dicendo di selezionare tutti i secondi elementi che si trovano all’interno dell’elenco.
Se desideri selezionare tutti i terzi elementi puoi scrivere 3n
, per i quarti 4n
e via dicendo…
Prima di andare ad analizzare il significato di n
però voglio mostrarti come selezionare tutti gli elementi dispari presenti nella nostra lista.
/* Seleziono elementi dispari con testo */ li:nth-child(odd){ /* Regole CSS */ } /* Seleziono elementi dispari con espressione */ li:nth-child(2n+1){ /* Regole CSS */ }
Grazie a quest’ultimo esempio adesso puoi comprendere meglio perché fino ad ora ho parlato di espressioni che possiamo passare a nth-child()
, grazie a questa pseudo-classe possiamo svolgere dei calcoli che aiutano a muoversi tra i vari elementi.
Per comprendere meglio perché l’espressione 2n+1
ci permette selezionare tutti i li
dispari è necessario capire che n
non è altro che un indice che parte da 0 e viene utilizzato internamente per calcolare il valore che renderà selezionato l’elemento specifico.
Cerchiamo di capirci meglio con questa piccola lista:
- n è uguale a 0 –
(2 x 0) + 1 = 1
(seleziona il primo elemento) - n è uguale a 1 –
(2 x 1) + 1 = 3
(seleziona il terzo elemento) - n è uguale a 2 –
(2 x 2) + 1 = 5
(seleziona il quinto elemento) - n è uguale a 3 –
(2 x 3) + 1 = 7
(seleziona il settimo elemento)
Questo è il calcolo che svolge il nostro browser quando si trova ad analizzare l’espressione 2n+1
, ma cosa succede se al posto di sommare andiamo a sottrarre dei numeri?
Adesso che sai come analizza l’espressione il tuo browser potresti fare anche il calcolo da solo ma vediamo come si comporta nth-child()
se passiamo come parametro 4n-2
:
- n è uguale a 0 –
(4 x 0) - 2 = -2
(nessun elemento selezionato) - n è uguale a 1 –
(4 x 1) - 2 = 2
(seleziona il secondo elemento) - n è uguale a 2 –
(4 x 2) - 2 = 6
(seleziona il sesto elemento) - n è uguale a 3 –
(4 x 3) - 2 = 10
(seleziona il decimo elemento)
Ecco spiegato il funzionamento delle espressioni quando vengono passate come parametro di nth-child()
ma prima di proseguire ecco un’utile tabella alla quale poter far riferimento.
E se la tabella non dovesse essere abbastanza chiara ti lascio anche qualche ulteriore esempio che ti aiuterà a comprendere ulteriormente il funzionamento di questa pseudo-classe e delle espressioni che possiamo inserire al suo interno.
Escludi i primi 5 elementi di una lista
li:nth-child(n+6){ /* Regole CSS */ }
Seleziona i primi 5 elementi di una lista
li:nth-child(-n+5){ /* Regole CSS */ }
Seleziona ogni quarto elemento a partire dal primo
li:nth-child(4n+1){ /* Regole CSS */ }
Altre utili pseudo-classi della famiglia nth-*
nth-child()
è soltanto una delle pseudo-classi che possiamo utilizzare nei nostri CSS per selezionare gli elementi in base alla loro posizione.
Con gli esempi che abbiamo visto precedentemente possiamo fare delle selezioni veramente avanzate ma ci sono alcune selezioni che sono impossibili da realizzare solo con questo.
Un esempio molto evidente che non possiamo risolvere con questa pseudo-classe sarebbe la selezione dell’ultimo elemento.
Già, come possiamo selezionare l’ultimo elemento utilizzando nth-child()
?
Non possiamo.
Per questo motivo è nato il prossimo selettore.
nth-last-child()
Questa nuova pseudo classe funziona esattamente come la precedente che abbiamo appena analizzato ma il suo indice viene calcolato a partire dall’ultimo elemento presente nella lista e non dal primo.
Quindi se voglio selezionare soltanto l’ultimo elemento presente questo è il codice che devo usare:
li:nth-last-child(1){ /* Regole CSS */ }
Proprio come quando abbiamo selezionato soltanto il quinto elemento con nth-child()
anche in questo caso abbiamo utilizzato un singolo valore numerico.
Però dato che nth-last-child()
funziona proprio come nth-child()
, cambia solo il calcolo dell’indice, anche all’interno delle sue parentesi tonde possiamo inserire delle espressioni utilizzando il valore n
.
Quindi se vogliamo selezionare gli ultimi cinque elementi della nostra lista utilizzando nth-last-child()
possiamo scrivere:
li:nth-last-child(-n+5){ /* Regole CSS */ }
Selezioniamo gli elementi per tipo e posizione
Fino ad ora quello che abbiamo fatto è stato selezionare un elemento in base alla sua posizione ma con il codice di partenza che avevamo non ci siamo accorti di un aspetto molto specifico, che cosa accade se sono presenti anche elementi differenti?
Come hai potuto scoprire nth-child()
e nth-last-child()
sono pseudo-classi che lavorano in base alla posizione di uno specifico elemento, per calcolare la posizione considerano l’elemento appartenente ad un insieme di altri elementi.
Questo insieme viene realizzato considerando l’elemento contenitore.
Tutti gli esempi che hai visto utilizzando queste pseudo-classi sono stati realizzati controllando i li
presenti all’interno di un ul
ma cosa succede se desidero modificare degli elementi che sono presenti all’interno di una struttura differente.
Diciamo una struttura come questa:
<article> <header> <h1> ... </h1> <p> ... </p> </header> <section> <h2> ... </h2> <p> ... </p> <p> ... </p> <p> ... </p> <h2> ... </h2> <p> ... </p> <p> ... </p> <p> ... </p> <h2> ... </h2> <p> ... </p> <p> ... </p> <p> ... </p> <h2> ... </h2> <p> ... </p> <p> ... </p> <p> ... </p> </section> <footer> <p> ... </p> <p> ... </p> <p> ... </p> </footer> </article>
Se desideri vedere un esempio dal vivo di questo esempio puoi controllare il CodePen che ho realizzato ma intanto cerchiamo di capire meglio perché non sempre nth-child()
si comporta come aspettato.
Come ti ho detto poco fa, in un elenco di elementi come una lista la pseudo-classe nth-child()
si comporta come desiderato. Se gli dico di selezionare ogni elemento pari gli stili applicati si visualizzano come desiderato, ma che succede se andiamo a scrivere qualcosa del genere basandoci sulla struttura precedente?
p:nth-child(2n){ background-color: #ccc; }
Per come siamo abituati, il nostro selettore dovrebbe applicare un grigio chiaro come sfondo di tutti i secondi p
che trova nell’insieme generato dall’elemento contenitore ma invece quello che ottengo è il seguente risultato.
Praticamente anche se il contenuto all’interno dell’elemento contenitore è misto, per esempio abbiamo dei titoli e dei paragrafi, nth-child()
non considera un conteggio separato ma andrà a selezionare i paragrafi che si trovano in posizioni pari.
Da un certo punto di vista, all’interno dell’<header>
il nostro paragrafo è il secondo elemento ma prima di lui c’è un h1
.
<header> <h1> ... </h1> <p> ... </p> </header>
Questo può sembrare un comportamento sbagliato, in fin dei conti se scrivo p:nth-child(2n)
mi aspetto di selezionare i paragrafi pari ma questo selettore non tiene conto dei tipi di elementi che lo circondano e per questo applicherà le nostre modifiche.
Per contare soltanto i paragrafi possiamo utilizzare due pseudo-classi specifiche:
nth-of-type()
nth-last-of-type()
Queste due pseudo-classi funzionano proprio come le precedenti ma la differenza sostanziale risiede nel fatto che in questo caso teniamo conto anche del tipo di elemento mentre contiamo la sua posizione.
Scrivendo per esempio p:nth-of-type(2n)
posso ottenere il conteggio corretto perché l’indice che sto utilizzando terrà conto solo dei paragrafi ed escluderà dal conteggio gli altri tipi di elementi presenti.
Conclusioni
Non posso che farti i miei complimenti perché se sei arrivato fino a qua significa che hai fatto un passo in più per migliorare le tue conoscenze dei CSS e sarai in grado di scrivere codice migliore.
In molti pensano che i CSS siano ormai un linguaggio poco interessante e si abituano ad utilizzare builder o il codice che viene generato da programmi come Sketch o Figma.
Io credo che sia proprio il contrario!
Negli ultimi anni anche i CSS hanno ricevuto molta attenzione, basta pensare alle Custom Property che hanno rivoluzionato la gestione dei valori che utilizziamo.
Sto dicendo questo perché voglio iniziare a pubblicare molti altri articoli dedicati a questo argomento e anche diversi corsi che si focalizzeranno su un singolo aspetto, come già successo per il corso su Flexbox.
Se anche a te interessa questo argomento la cosa migliore che puoi fare è iscriverti alla nostra newsletter grazie al modulo che trovi proprio qua sotto.
Lascia un commento