CogitoWeb

6 luglio 2010

Box Model: alla fine avevano ragione “loro”

Filed under: CSS — MaxArt @ 02:14
Tags: , , ,
Se vi dovessero chiedere la lunghezza della vostra auto, molto probabilmente voi prendereste un metro e misurereste la distanza tra il paraurti anteriore e quello posteriore. Non vi verrebbe mai in mente di dire che la lunghezza è la distanza tra il cruscotto ed il lunotto posteriore. Similmente, se vi chiedessero le dimensioni di una scatola di scarpe, voi la misurereste dai bordi esterni, e non quelli interni sebbene la differenza sia minima.

A questo devono aver pensato alla Microsoft tanto, tanto tempo fa, sviluppando la prima versione di Internet Explorer (era il 1995). La domanda era: come dobbiamo intendere le dimensioni di un elemento HTML? A cosa si definiscono i valori di width e di height? Come qualsiasi sviluppatore web saprà, un elemento HTML è caratterizzato da tre “spessori”:

  • margin: si tratta di uno spazio vuoto che viene frapposto tra l’elemento e quelli che lo circondano;
  • border: il bordo dell’elemento, disegnato in vari modi e colori;
  • padding: un ulteriore spazio che specifica la distanza tra il bordo dell’elemento ed il suo contenuto.

L’idea di Microsoft era che width e height si dovessero riferire alle dimensioni dell’elemento includendo bordi e padding, andando cioè così a delimitare l’area effettivamente visibile dell’elemento. Questa in effetti pare la scelta più logica, ma così non sembrò alla Netscape, sviluppatore del browser concorrente Navigator: per loro, la scelta migliore era definire le dimensioni come quelle del contenuto dell’elemento. Fu così che, per Internet Explorer, un elemento largo 100 pixel, con 5 pixel di bordo e 10 di padding, visualmente era largo effettivamente 100 pixel, mentre era largo 130 pixel per Netscape Navigator. E non c’era modo di conciliare la cosa: inutile dire che era un brutto periodo per i webmaster…

A questo si aggiunse che il consorzio W3 per la definizione degli standard web decise, a sorpresa, di dare ragione all’idea di Netscape: larghezza e altezza sono quelli del contenuto e non della scatola. Beh, poco male: in fondo l’importante era che venisse presa una decisione definitiva, perché in sostanza i due box model sono equivalenti, giusto? Sbagliato! Perché l’uso del box model di casa Microsoft, oltre ad essere intuitivamente più ragionevole, consente di “giocare” molto più liberamente con le dimensioni, permettendo in sostanza di mischiare le unità di misura. Cosa vuol dire questo?

Supponiamo di voler mettere un elemento <div> all’interno di un altro, in modo che occupi tutto lo spazio possibile in larghezza. Se conoscessimo la dimensione in pixel (o qualche altra unità di misura) la cosa sarebbe banale, ma in caso contrario si può sempre ricorrere alle percentuali, in questo modo:

<div>
   ...
   <div style="width: 100%">Testo inserito</div>
   ...
</div>

L’effetto è quello voluto:

Testo inserito

Ma se volessimo definire un padding di qualche pixel all’interno del div interno? Cosa accadrebbe? Forse qualcuno avrà già intuito il problema, ma partiamo direttamente dal risultato:

Testo inserito

Il <div> ha sbordato! E, per la precisione, di 20 pixel (è stato messo un padding di 10 pixel). Tutto questo, a ben pensarci, è ovvio: l’indicazione width: 100% si riferirà all’area del contenuto, ed è quella che sarà definita larga quanto l’elemento contenitore. La definizione del padding aggiunge in sostanza uno spessore esterno a quest’area, ed il risultato è così spiegato. Col box model di Microsoft, invece, non avremmo avuto questo problema.

Inutile pensarci su: non c’è alcun modo di risolvere questo problema, almeno con il solo uso dei fogli di stile. Se abbiamo usato le percentuali, saremo costretti a mettere dei padding con le percentuali, sottraendo il loro valore da quello di width. L’unico modo per ottenere l’effetto desiderato è quello di calcolare trmite JavaScript la larghezza in pixel dell’elemento contenitore ed in base a questo definire la larghezza del nostro <div> interno. Bella rogna, eh? Tutto per un effetto così semplice. E la cosa diventa ancora più ridicola se magari l’elemento contenitore ha una larghezza variabile e modificabile dall’utente (ad esempio, in un sito la cui struttura è stata definita con le percentuali): per ottenere un effetto di fluidità, bisogna effettuare un ricalcolo “al volo” delle dimensioni, con evidenti rallentamenti in caso di computer più vecchi (o di uno smartphone), quando un lavoro del genere è tipico del motore di rendering del browser, solitamente ben più efficiente.

Un altro esempio potrebbe essere, per l’appunto, quello di un sito la cui struttura è stata sviluppata usando le percentuali. Se volessimo avere, ad esempio, due sezioni larghe al 50% una accanto all’altra, non potremmo metterci né bordi, né padding, perché alla fine risulterebbero più larghe della metà della pagina e quindi la seconda andrebbe “a capo” (cioè sotto la prima).

Nel 2001, Internet Explorer 6 venne pubblicato e garantì il supporto al box model definito dal W3C, a patto che venisse messa una dichiarazione <!DOCTYPE> all’inizio del documento; nel caso contrario, usava il box model tradizionale di casa Microsoft. Gran parte dei webmaster si adeguarono al W3C, ma almeno da questo punto di vista fu una gran perdita. Tant’è vero che ora il W3C sembra essere tornato sui suoi passi, o quantomeno è intenzionato a lasciare la libertà agli sviluppatori di decidere che box model usare: con le nuove specifiche CSS3, infatti, verrà introdotta la proprietà box-sizing, che potrà assumere i valori content-box (di default, per lo standard W3C) o border-box (per il box model tradizionale).

Purtroppo, le specifiche del CSS3 sembrano non diventare mai definitive, ed ogni volta la loro uscita viene ritardata. Mentre le specifiche CSS1 vennero rilasciate nel 1996 e quelle CSS2 nel 1998, le specifiche CSS3 videro cominciare il loro sviluppo nel 1999 ma a distanza di ben 11 anni ancora non sono definitive. Fortunatamente, il W3C pubblica di continuo i lavori di sviluppo e molti browser si sono già adattati ad usare parte delle nuove specifiche già prima del tempo (col rovescio della medaglia per cui talvolta i risultati sono errati o fuori standard). In particolare, box-sixing (col prefisso -moz-) è stata adottata da Firefox già dalla versione 1.0, da Safari (col prefisso -webkit-) dalla versione 3, da Chrome (sempre con -webkit-), da Opera dalla versione 8.5 e Internet Explorer 8 (questi due senza prefissi). Ironicamente, quindi, proprio Internet Explorer è stato l’ultimo browser a seguire il “ritorno alle origini”…

Se avete uno dei suddetti browser, il risultato dovrebbe assomigliare a questo:

Questo è il codice relativo:

<div>
   ...
   <div style="width: 100%; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;">Testo inserito</div>
   ...
</div>

Si noti la specifica multipla della proprietà per Firefox e Safari/Chrome: in futuro non sarà più necessaria.

Nota: per modificare la proprietà con JavaScript, si agisce sulla proprietà boxSizing dell’oggetto di stile (MozBoxSizing in Firefox, WebkitBoxSizing in Safari/Chrome). Si noti che, sebbene sia uguale a “” e non a undefined, in Internet Explorer 7 la proprietà non è supportata!

Crea un sito o un blog gratuitamente presso WordPress.com.