La proprietà CSS nth-child: come stilizzare e cambiare il colore di sfondo nelle righe delle tabelle HTML

In un progetto recente mi è capitato di dover creare alcune tabelle per mostrare un tariffario medico. Quando si rappresentano dati tabulari, il rischio di essere poco chiari è dietro l’angolo, soprattutto se la quantità del testo è consistente: nel saltare da una riga all’altra, l’occhio potrebbe confondersi (se poi il carattere è molto piccolo… disastro!). Alternare il colore di sfondo delle righe può essere banale, ma rappresenta un’ottima soluzione! Esiste però un modo “economico” e veloce per realizzarlo con il CSS?

Un problema di ordine...

Questo è l’effetto che voglio ottenere:

Nome servizio Prezzo Minuti
Servizio 1 20 € 10
Servizio 2 40 € 20
Servizio 3 10 € 5
Servizio 4 30 € 15

Ho deciso di affidarmi ad uno strumento che adoro: il forum di CSS-Tricks. E la risposta è arrivata dopo neanche due ore! Mi è stato infatti suggerito (e mostrato) come sfruttare a tal vantaggio la proprietà nth-child. La definizione del W3C dice che tale proprietà serve ad intercettare ogni “ennesimo” elemento figlio (child) di un dato contenitore (parent) a prescindere dal tipo di oggetto in questione. Per esempio, le righe (<tr>) di una tabella si possono proprio considerare “figlie” dell’oggetto che le contiene: la “tabella” (<table>).

Come funziona

Ogni volta che incontro una nuova proprietà CSS, per prima cosa controllo sempre la compatibilità con i vari browsers: in questo caso, scopro che nth-child è largamente supportata. Naturalmente, la pecora nera è sempre Internet Explorer: dalla versione 8 (compresa) verso il basso, possiamo scordarci che venga rispettata. Ne riparlerò più avanti, per ora ecco il codice HTML della mia tabella:


<table>
<tbody>
<tr>
<th>Nome servizio</th>
<th>Prezzo</th>
<th>Minuti</th>
</tr>
<tr>
<td>Servizio 1</td>
<td>20 €</td>
<td>10</td>
</tr>
<tr>
<td>Servizio 2</td>
<td>40 €</td>
<td>20</td>
</tr>
<tr>
<td>Servizio 3</td>
<td>10 €</td>
<td>5</td>
</tr>
<tr>
<td>Servizio 4</td>
<td>30 €</td>
<td>15</td>
</tr>
</tbody>
</table>

Ed ecco la proprietà nth-child in azione:


tr:nth-child(even) {

background-color: grey;
}

Esatto, tutto qui! Ecco spiegato in dettaglio che cosa ho scritto:

  • tr: è l’oggetto che voglio intercettare (la riga della mia tabella)
  • :nth-child: il codice che richiama la proprietà
  • (even): rappresenta il “parametro” (discriminante) di selezione. even significa “pari”, ed infatti ho intercettato e cambiato il colore di sfondo a tutte le righe “pari” della tabella

I più esperti riconosceranno nth-child come quello che in realtà è: una pseudo-classe (le “pseudo classi” si riconoscono sempre dalla presenza dei “:”). E se avessi voluto intercettare solo le righe “dispari”? Semplice: avrei dovuto scrivere odd al posto di even.

Ma nth-child è molto più di questo...

Esco per un attimo dall’esempio pratico del tariffario medico, per dire che in realtà la proprietà nth-child può essere usata in modo molto più complesso, fino a far fronte a una larga scala di applicazioni. Ad esempio, se volessi cambiare colore a tutti gli elementi <li> di una lista che sono multipli di 3:

  • Elemento 1
  • Elemento 2
  • Elemento 3
  • Elemento 4
  • Elemento 5
  • Elemento 6
  • Elemento 7
  • Elemento 8
  • Elemento 9

Il CSS diventerrebbe:


li:nth-child(3n + 0) {

color: red;
}

Entrano così in gioco due nuovi elementi: 3n (n è una variabile, mentre 3 il suo coefficiente) e un numero (in questo caso 0) che chiamerò “offset”. Il gioco sta nel risolvere l’equazione 3n + 0, dove a variare è sempre e solo il valore di n (si parte da 0 e si percorrono tutti i numeri interi positivi fino all’infinito). Che spiegazione ostica… Per fortuna che la soluzione è facilissima!

  • n = 0 => 3n + 0 = 0
  • n = 1 => 3n + 0 = 3
  • n = 2 => 3n + 0 = 6
  • n = 3 => 3n + 0 = 9
  • n = 4 => …

In pratica, nth:child ha selezionato gli elementi di indice 3, 6 e 9 (non esiste infatti l’elemento 0, e se la mia lista fosse stata più lunga l’equazione non si sarebbe nemmeno fermata a 9). E adesso ancora più difficile! (4n + 1):

  • Elemento 1
  • Elemento 2
  • Elemento 3
  • Elemento 4
  • Elemento 5
  • Elemento 6
  • Elemento 7
  • Elemento 8
  • Elemento 9

Ovvero:

  • n = 0 => 4n + 1 = 1
  • n = 1 => 4n + 1 = 5
  • n = 2 => 4n + 1 = 9
  • n = 3 => …

Posso anche semplificare al massimo, indicando un solo parametro (4):

  • Elemento 1
  • Elemento 2
  • Elemento 3
  • Elemento 4
  • Elemento 5
  • Elemento 6
  • Elemento 7
  • Elemento 8
  • Elemento 9

C’è bisogno di spiegarlo?

Per finire, si possono anche usare dei numeri negativi, sia sul coefficiente di n (come (-n + 3)), sia davanti al valore di offset (ad esempio (2n - 6)). Qualcuno potrebbe chiedersi che senso avrebbe usare valori negativi… Ed ecco che invece salta fuori essere un trucchetto molto utile! Ad esempio, se voglio selezionare solo i primi 5 elementi di una lista, posso usare (-n + 5). Infatti:

  • n = 0 => -n + 5 = 5
  • n = 1 => -n + 5 = 4
  • n = 2 => -n + 5 = 3
  • n = 3 => -n + 5 = 2
  • n = 4 => -n + 5 = 1
  • n = 5 => -n + 5 = 0 (nulla)

Se hai ancora dubbi sul funzionamento della proprietà nth-child o semplicemente vuoi testare il risultato prima di applicarlo in un caso reale, CSS-Tricks offre un comodo tool fatto apposta per questo scopo.

Il supporto per Internet Explorer 8 (e inferiori)

Nel caso fossi obbligato a supportare anche i browser più “capricciosi”, puoi sfruttare ad esempio la libreria Javascript Selectivizr, che è stata scritta apposta per emulare i più recenti selettori anche in versioni obsolete di Internet Explorer: la 6, la 7 e 8. Non spiego qui come utilizzare la libreria (è spiegata benissimo anche sul sito ufficiale), ma magari in futuro ne farò un tutorial…