cat html-css/collasso-dei-margini-verticali-quando-due-margini.md

Lezione 22 15 min

Collasso dei margini verticali: quando due margini diventano uno

Uno dei comportamenti più incompresi del CSS. Scopri perché 20px + 30px di margine a volte fa 30px, e come gestire questa anomalia.

Il Box Model è generalmente molto logico e prevedibile, tranne per una bizzarra caratteristica storica chiamata Collasso dei Margini (Margin Collapse).

Cos’è il collasso dei margini?

Se metti due elementi blocco uno sotto l’altro (es. due paragrafi) e assegni un margine inferiore al primo e un margine superiore al secondo, ti aspetteresti che i due margini si sommino. Il CSS, invece, li fa “collassare” in un unico margine.

Il margine risultante non sarà la somma matematica, ma prenderà semplicemente il valore del margine più grande tra i due.

Guardiamo questo esempio:

<h2 class="titolo">Il mio titolo</h2>
<p class="paragrafo">Questo è il paragrafo sotto il titolo.</p>
.titolo {
  margin-bottom: 30px; /* Margine SOTTO il titolo */
}

.paragrafo {
  margin-top: 20px; /* Margine SOPRA il paragrafo */
}

Istintivamente penseresti che la distanza tra i due sia 30px + 20px = 50px. Sbagliato! La distanza sarà esattamente 30px, perché i margini collassano e vince il più grande.

Perché il CSS fa questo?

Non è un bug, è una feature progettata negli anni ‘90 pensando alla tipografia classica, dove si impilavano decine di paragrafi e titoli. Il collasso evita che tra la fine di un paragrafo e l’inizio del successivo si creino spazi vuoti abnormi e sbilanciati. Rende la spaziatura verticale della lettura molto più omogenea senza dover usare classi speciali.

Regole d’oro del collasso

  1. Solo in verticale: I margini destra/sinistra non collassano MAI. margin-left e margin-right si sommano sempre matematicamente.
  2. Solo elementi adiacenti: Devono toccarsi. Se in mezzo ci metti un bordo, del padding o un <hr>, il collasso viene interrotto e i margini tornano a sommarsi.
  3. Collasso genitore-figlio: Attenzione! Il margine superiore del primo figlio collassa “fuori” dal genitore se il genitore non ha né bordi né padding in cima. Se ti trovi a chiederti “Perché spostando questo titolo verso il basso si sposta anche il contenitore?”, è colpa del collasso genitore-figlio!

La soluzione moderna: Single Direction Margin

Poiché il collasso dei margini causa spesso confusione, la comunità ha sviluppato una best practice eccellente: il margine a direzione singola.

L’idea è semplice: definisci i margini solo in una direzione verticale per tutto il tuo progetto. Quasi tutti scelgono margin-bottom (spingere verso il basso).

h1, h2, h3, p, ul {
  margin-top: 0; /* Azzera sempre i margini superiori! */
  margin-bottom: 1.5rem; /* Definisci solo lo spazio in basso */
}

Se tutti gli elementi spingono solo verso il basso e non hanno spazio sopra, elimini del tutto la possibilità che si verifichi un collasso inaspettato tra due elementi fratelli!