Pillole CSS: che cos’è il box model e come sfruttarlo per i nostri layout?
Negli ultimi due articoli abbiamo visto come strutturare un layout fisso a due e tre colonne utilizzando i float opposti, e abbiamo costruito una piccola pagina di esempio. Il risultato era accettabile, ma risultava un po’ troppo “attaccato”: ogni elemento era confinante con l’altro, appesantendo il tutto.
Proviamo a rendere più presentabile il layout sfruttando il box model.
Come già accennato nella conclusione dello scorso articolo, il problema del nostro layout era che gli elementi spaziavano per tutta la larghezza del contenitore, dato che avevamo impostato solo le width. Questo è il markup di riferimento:
<body> ... <div id="contenitore-ricetta"> <div id="ricetta"> <h2>Ciambellone bigusto</h2> ... </div> <div id="ingredienti"> <h2>Ingredienti</h2> ... </div> </div> <!-- fine ricetta esterno --> <div id="ricette_simili"> <h2>Ricette simili</h2> ... </div> ... </body>
A cui erano applicate le seguenti regole CSS:
body {
...
width: 1000px;
}
#ricette_simili {
...
width: 200px;
}
#ricetta {
...
width:600px;
}
#ingredienti {
...
width:200px;
}
Aggiungendo degli sfondi agli elementi, il problema è molto più evidente: come vedi non c’è nessun canaletto tra le varie colonne (che tra l’altro non si estendono nemmeno per tutta la lunghezza del layout). Una possibile soluzione è impostare i margini destro e sinistro all’elemento centrale, in questo modo:
#ricetta {
...
margin-left: 30px;
margin-right: 30px;
width:600px;
}
Andando a vedere il risultato non troviamo esattamente l’effetto sperato: l’elemento centrale si è spostato a sinistra, costringendo la colonna di sinistra a spostarsi in basso. Perché è successo questo? La chiave per rispondere a questa domanda è la comprensione del box model.
Le basi del box model
Fondamentalmente per i CSS esistono due tipi di elementi: gli elementi inline e gli elementi di blocco (Nota: esistono anche altri tipi, però sono molto meno utilizzati).
Grossolanamente parlando, gli elementi di blocco sono quelli che generano una nuova riga prima e dopo nel flusso del documento, occupandone tutta la larghezza. Un esempio di elementi di blocco sono i div, i paragrafi, i titoli (h1, h2, ecc.). Gli elementi inline invece sono quelli che stanno su una riga, all’interno di un testo. Ad esempio il tag span, oppure strong sono elementi inline. In questo articolo ci occuperemo degli elementi di blocco.
Come suggerisce il nome, tali elementi creano un riquadro nel documento. I componenti di tale riquadro, oltre alla width, sono margini, padding e bordi. Lo schema di un generico elemento di blocco potrebbe essere il seguente:

Esaminiamo questi elementi uno per volta:
- Larghezza: rappresenta l’ampiezza dell’area in cui è posto il contenuto dell’elemento.
- Padding: a volte chiamato “margine interno” è la distanza del contenuto dal bordo interno.
- Bordo: è il bordo dell’elemento.
- Margine: è uno spazio (trasparente) che circonda il blocco, impedendo agli altri elementi sovrapporsi ad esso.
Immaginando il blocco come un pacco, la larghezza è rappresentata dalle dimensioni del contenuto, il padding dall’imballaggio interno al pacco, il bordo è rappresentato dai limiti della scatola, mentre il margine è lo spazio che lo separa dagli altri pacchi.
La cosa fondamentale da capire riguardo al box model è che la larghezza di un elemento è data dalla width più il valore dei margini, del padding e dei bordi. Ovvero, se io imposto la width di un elemento a 100 pixel, e i margini destro e sinistro a 10 px ognuno, l’elemento risulterà largo complessivamente 120 pixel. Questo comportamento è un po’ controintuitivo: se io ho impostato una larghezza ad un elemento vorrei che fosse quella, nonostante margini o bordi. Purtroppo è questo il comportamento deciso dal W3C e a noi non resta che adeguarci.
Per fissare le idee dunque, un riquadro orizzontale è calcolato in questo modo: margine sinistro + bordo sinistro + padding sinistro + larghezza + padding destro + bordo destro + margine destro.
Modifichiamo il nostro esempio
Avrai quindi capito che il problema nel nostro esempio precedente era dovuto al fatto che l’elemento centrale aveva assunto una larghezza di 30 + 600 + 30 = 660pixel. Dato che la larghezza del contenitore è di 1000 pixel, i tre elementi sforano tale ampiezza, risultando in un layout sballato. Come risolvere questo problema?
La soluzione è molto semplice, anche se coinvolge alcuni calcoli matematici: in pratica bisogna sottrarre dall’ampiezza voluta dell’elemento, la somma delle ampiezze di margini, bordi e padding. Nel nostro esempio, avendo impostato solo i margini destro e sinistro a 30 pixel, dobbiamo effettuare la sottrazione 600 – (30 + 30) = 540 pixel. Questa sarà la width da impostare per l’elemento centrale, in questo modo:
#ricetta {
...
margin-left: 30px;
margin-right: 30px;
width:540px;
}
E come puoi vedere nell’esempio, ora tutti gli elementi sono rimasti al loro posto. Se avessi voluto aggiungere 20 pixel di padding ad entrambi i lati, ed un bordo di 1 pixel, la sottrazione sarebbe stata 600 – (30 + 1 + 20 + 20 + 1 + 30) = 518 pixel, e avrei ottenuto questo risultato
Il marginator
Per esperienza personale, so che spesso l’introduzione di formule matematiche non è bene accetta, dunque ho realizzato questo piccolo script (con l’aiuto di jQuery): il Marginator. Il Marginator permette di ricavare la larghezza da impostare ad un elemento nel modo più intuitivo possibile: si imposta la larghezza dell’elemento, gli eventuali margini, padding o bordi, ed il risultato sarà la larghezza da associare alla proprietà width dell’elemento.
14 commenti
Trackback e pingback
Non ci sono trackback e pingback disponibili per questo articolo





Ciao Just, mi piace molto il marginator :D !!!!
Ottimo articolo!
Grazie Nicolas! È un onore per me ricevere i tuoi complimenti :)
Bellissima spiegazione… tempo addietro ero arrivato a questa soluzione, dopo che mi scervellavo tutto per capire perchè impostando dei padding, mi si sballava tutto.
Come hai scritto tu, è una cosa controintuitiva e sono daccordo, soprattutto parlando dell’aggiunta di padding e bordi: se io imposto una larghezza con width, intuitivamente voglio impostare la larghezza interna, senza pensare ne a padding, ne a bordi. Quelli sono una cosa in più, che modificano la posizione del contenuto all’interno di questo blocco.
Perchè aggiungere un padding, deve far aumentare il box? (su questo punto di vista, IE interpretava in questo modo e, secondo me, non è molto sbagliato)
MA, finalmente la capì e mi sono adeguato di conseguenza.
Come ho già detto, mi trovi d’accordo su questa questione.
Questo tipo di problemi si presenta quando manca la comunicazione tra gli ideatori e gli utilizzatori finali di un linguaggio.
Chiaramente cambiare standard a questo punto sarebbe impossibile, quindi non resta che adattarci e cercare di afferrare questi concetti basilari :)
Articolo scritto molto bene, vedo che hai utilizzato solo i margini per evitare problemi con IE6, credo però sia importante ricordare il suo “problemino” col box model ovvero che nella larghezza (width) dell’elemento vengono inclusi anche il padding e border.
Metto un link per chi vuole approfondire i problemi con IE6 (inglese): http://css-tricks.com/ie-css-bugs-thatll-get-you-every-time/
Ciao Paolo,
sono contento che tu abbia portato alla luce questa questione.
L’omissione è stata volontaria, per almeno due ragioni:
1) IL box model standard è quello presentato nell’articolo, mentre quello di IE è una “deformazione proprietaria”. Credo che questa distinzione possa portare non pochi fraintendimenti per chi si avvicina per la prima volta a questi argomenti.
2) Il problema del box model differente (ovvero il calcolo dei margini, padding e bordi compresi nella width) è un bug di IE5.
IE6 presenta questo bug solo in Quirks mode, ovvero quando manca la definizione del DOCTYPE, e quindi si comporta come IE5.
Ma credo che, al 2010, poche persone utilizzino IE5, e pochissimi sviluppatori omettano la definizione del DOCTYPE (altrimenti non li considererei sviluppatori ;) )
Un pensiero a posteriori però mi fa pensare che una trattazione completa è sempre migliore di una “manchevole”, quindi ti ringrazio ancora per la puntualizzazione :)
A presto.
gran bel lavoro
grazie
:)
Grazie a te iteand :)
Articolo semplice e completo, bravo!
Una cosa strana succede nel Marginator:
andando avanti per i campi col tab, arrivato quindi al risultato, spostandomi col pad del portatile per fare lo scroll della pagina…il risultato aumenta se vado giù, diminuisce se vado su :-D
Idem se mi sposto su uno dei campi e “scrollo”.
Ciao Silvio, e benvenuto su YIW.
Grazie per i complimenti :)
Per quanto riguarda il Marginator, quello dello scroll è un esperimento voluto. Se noti infatti, accanto ad ogni campo “scrollabile” c’è una piccola iconcina di un mouse, che indica la possibilità di aumentare/diminuire il valore con la rotella del mouse ;)
A presto
Che figuraaaa :-D ed io che mi chiedevo perchè c’erano quelle iconcine lì…
Illuminante! Grazie e complimenti.
ottimo lavoro…
grazie mille
Davvero un ottimo lavoro.. e anche per il Marginator
Grazie