cat html-css/specificita-calcolo-a-tre-cifre-0-0.md

Lezione 14 20 min

Specificità: calcolo a tre cifre (0,0,0) e strategie pratiche

Impara a calcolare matematicamente quale regola CSS vincerà sulle altre e scrivi codice manutenibile senza ricorrere a hack.

Nella lezione precedente abbiamo visto che la cascata favorisce il selettore più “specifico”. Ma come fa il browser a sapere quale selettore è più specifico di un altro? Lo fa tramite una formula matematica.

Per il CSS scritto nei fogli di stile, la specificità si può studiare con un sistema a tre colonne: (0, 0, 0). Gli stili inline e alcune funzioni moderne aggiungono dettagli che vedremo come note, ma questo modello è la base più utile per iniziare.

Ecco i tre livelli, dal più forte al più debole:

  1. (1, 0, 0) - ID: I selettori con l’hash (#navbar).
  2. (0, 1, 0) - Classi, attributi e pseudo-classi: I selettori col punto (.btn), tra parentesi quadre ([type="text"]), e gli stati (:hover).
  3. (0, 0, 1) - Elementi (Tag) e pseudo-elementi: Tag HTML normali (p, h1) e gli pseudo-elementi (::before).

Il selettore universale (*) e combinatori (>, +, ~) hanno specificità zero (0, 0, 0).

Come calcolare il punteggio

Per calcolare la specificità di un selettore, conta quanti ID, classi/attributi e tag contiene. Poi scrivili uno accanto all’altro (come se fosse un numero a 3 cifre, anche se non si effettuano veri e propri riporti decimali).

Guardiamo alcuni esempi:

  • h1 → 1 tag = (0, 0, 1)
  • ul li a → 3 tag = (0, 0, 3)
  • .menu-link → 1 classe = (0, 1, 0)
  • nav.menu-link → 1 tag + 1 classe = (0, 1, 1)
  • a:hover → 1 tag + 1 pseudo-classe = (0, 1, 1)
  • #header .logo img → 1 ID + 1 classe + 1 tag = (1, 1, 1)

La battaglia matematica

Quando c’è un conflitto, il browser confronta i numeri partendo da sinistra (la colonna più forte).

/* Punteggio: (0, 1, 1) */
ul .evidenziato { color: blue; }

/* Punteggio: (0, 2, 0) */
.menu .evidenziato { color: red; }

Chi vince? Vince il rosso (0, 2, 0) perché 2 classi battono 1 classe e 1 tag.

/* Punteggio: (0, 15, 0) */
.a.b.c.d.e.f.g.h.i.l.m.n.o.p.q { color: blue; }

/* Punteggio: (1, 0, 0) */
#titolo { color: red; }

Chi vince? Vince il rosso. Nel confronto della specificità, un ID batte qualunque numero di classi nello stesso selettore.

Due note moderne

La pseudo-classe :where() ha specificità zero. È utile quando vuoi scrivere selettori comodi senza renderli più difficili da sovrascrivere.

:where(article, section) h2 {
  margin-block: 2rem 1rem;
}

Le pseudo-classi :is() e :not() prendono invece la specificità dal selettore più specifico che contengono.

:is(.card, #featured) h2 {
  color: darkblue;
}

Non devi padroneggiarle subito, ma devi sapere che la specificità moderna non è solo una tabella da imparare a memoria.

Strategie pratiche (e best practice)

Un buon CSS ha una specificità bassa e piatta. Se i tuoi selettori sono troppo complicati, andrai incontro all’inferno della manutenzione, noto come Specificity Wars (le guerre della specificità).

Cosa NON fare:

/* Specificità troppo alta e rigida: (1, 1, 2) */
#main-content ul.lista-articoli li {
  color: black;
}

Se in futuro vorrai sovrascrivere il colore di un particolare list item, sarai costretto a creare un selettore ancora più specifico o usare !important.

Cosa FARE:

/* Specificità ideale: (0, 1, 0) */
.articolo-item {
  color: black;
}

Assegna semplicemente una classe al tag <li> nell’HTML (class="articolo-item") e seleziona direttamente quella. Questo approccio è la base della metodologia BEM (Block Element Modifier), che insegna a mantenere il CSS piatto e modulare.

Regola riassuntiva:

  1. Non usare gli ID per lo stile (#).
  2. Usa le classi (.) come fondamento di quasi tutto.
  3. Mantieni i selettori corti (massimo 2-3 livelli di annidamento).