Il collasso dei margini verticali è uno di quei comportamenti che i fogli di stile hanno ereditato dai browsers di prima generazione, quando il CSS ancora non esisteva. Prima di capire come funziona, inquadriamo l'argomento. Il collasso dei margini entra in gioco solamente se
- Abbiamo due o più elementi di blocco adiacenti o innestati
- Si parla di margini verticali (margin-top o margin-bottom)
Il collasso non si applica nel caso di margini orizzontali, né per gli elementi in linea. La motivazione del collasso dei margini verticali è dettata dal buon senso. Consideriamo una sequenza di elementi HTML
<span>A plain span element</span>
<p style="MARGIN:1px 0px;">First paragraph</p>
<p style="MARGIN:20px 0px;">Second paragraph</p>
<p style="MARGIN:20px 0px;">Third paragraph</p>
<span>Another plain span element</span>
che viene renderizzata grossomodo così
Collasso del margine verticale (elementi adiacenti)
come si vede dalla figura, la distanza tra il 2° e il 3° paragrafo è di 20px, e non di 40px, come ci si potrebbe aspettare sommando il margine inferiore del 2° paragrafo (pari a 20px) con il margine superiore del 3° paragrafo (pari a 20px). Questo comportamento si chiama collasso del margine verticale, perché i due margini sono stati “uniti” in un unico margine, anziché sommati. E' un comportamento che nella maggior parte dei casi torna comodo, perché permette di garantire il rispetto dei margini impostati. La regola del collasso del margine verticale è la seguente:
Quando due o più elementi di blocco sono adiacenti o nidificati, il margine verticale è pari al massimo dei valori dei singoli margini.
La regola permette di identificare la dimensione del margine verticale senza ambiguità. Consideriamo ad esempio
<p style="MARGIN:10px 0px;">First paragraph</p>
<p style="MARGIN:20px 0px;">Second paragraph</p>
Il primo paragrafo ha un margin-bottom pari a 10px, per cui si aspetta che l'elemento successivo (il 2° paragrafo) si collochi 10px più in basso. Il secondo paragrafo ha margin-top pari a 20px, quindi cercherebbe di posizionarsi 20px sotto il precedente. Quale di queste due distanze separerà i paragrafi, quando verranno renderizzati da un browser? Se il margine effettivo risultasse la somma dei due (30px) non avremmo rispettato nessuno dei due stili: scegliendo invece il valore massimo (20px) si ottiene un buon compromesso, dettato dal buon senso.
Fin qui tutto bene. Il collasso dei margini verticali può invece risultare scomodo se trattiamo degli elementi di blocco nidificati l'uno dentro l'altro, ovvero annidati o innestati. Prendiamo un paio di div
annidati e vediamo cosa succede
<span>A plain <code>span</code> element</span>
<div style="MARGIN:10px 0px; BACKGROUND-COLOR:blue;">
<div style="MARGIN:20px 0px; BACKGROUND-COLOR:cyan;">
Content
</div>
</div>
in seguito al collasso dei margini verticali, in questo caso avremo un unico margine verticale, pari al massimo tra i valori 10px e 20px, che è 20px. La novità è che adesso tale margine verrà applicato solamente all'elemento esterno, ovvero al div
contenitore.
Collasso del margine verticale (elementi nidificati)
il risultato è che il div
interno, quello di colore cyan, non sarà separato dal div
esterno, ma i due elementi risulteranno “incollati verso l'alto”, come se avessero lo stesso bordo superiore. In altre parole avremo un margine di 20px per il div
esterno (anche se è settato a 10px), e un margine di 0px sul div
interno (anche se è settato a 20px).
Nel caso degli elementi di blocco annidati, il collasso dei margini può risultare fastidioso. Per evitarlo possiamo sfruttare le condizioni che inibiscono il collasso. Il collasso verticale infatti non avviene nel caso che:
- Se l'elemento contenitore ha un bordo
- Se l'elemento contenitore ha un valore di padding
- Se uno degli elementi è “galleggiante” (
float
) - Se uno degli elementi ha posizione assoluta (
position: absolute
)
Un altro modo di risolvere il problema potrebbe essere quello di sfruttare la proprietà CSS overflow, che però merita di essere trattata a parte e preferiamo non introdurla oggi. Le quattro condizioni elencate qui sopra dovrebbero essere sufficienti per controllare il layout verticale del box model.... senza margine d'errore.