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

Aggiornato il

Un problema di ordine…

In un progetto recente, ho dovuto 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?

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! Paulie_D mi ha 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…

Riferimenti

di Mattia Frigeri