CSS Zibaldone

[ Home ] - [ Articoli ] - [ Traduzioni ] - [ Altro ] - [ Appunti sui CSS ] - [ L'autore ]

Sei qui: Home > Traduzioni > Box model hack

Box model hack

Articolo originale: http://css-discuss.incutio.com/?page=BoxModelHack

Traduzione: Gabriele Romanato (17 agosto 2007)

Perché il box model ha bisogno di un hack?

Secondo il W3C, una 'width' (o 'height') assegnata ad un box si riferisce solo all'area di contenuto del box. Il padding, i bordi ed i margini vengono sommati in un secondo momento per arrivare alla larghezza totale del box. Se la proprietà 'width' viene omessa, la larghezza totale del box coincide con l'area di contenuto dell'elemento contenitore del box.

Tutto giusto. Sfortunatamente, tutte le versioni di Internet Explorer precedenti alla 6 usano un box model differente. In questo modello, il padding e i bordi vengono considerati come parte di ogni 'width' o 'height' assegnata. In assenza di bordi e padding, i due modelli concordano. Tuttavia, se un box ha una larghezza assegnata e gli vengono aggiunti bordi e padding, il box model standard fa si che la larghezza complessiva del box aumenti, mentre nel modello di Internet Explorer l'area di contenuto comprende tutte le misure. Questo è un grande problema nella realizzazione di un corretto layout di pagina.

Si consideri il seguente CSS:

{
width:100px; 
padding:10px; 
border:10px;
}

Se visto in un browser standard, la dimensione da bordo a bordo sarà di '140px' (100+10+10+10+10=140). Dato che Internet Explorer 5.x calcola questi valori all'interno di 'width', la dimensione da bordo a bordo sarà di '100px'.

Nota: Per motivi tecnici a volte si vuole adottare il vecchio box model di Internet Explorer. Si è parlato di una caratteristica dei fogli di stile di livello 3 che permetterebbe di scegliere tra i due modelli, ma l'attuale modello standard resterà senza dubbio come quello predefinito.

Arriva il box model hack. Bisogna dare ad Internet Explorer 5.x/Windows, e solo a quel browser, un valore di 'width' addomesticato (140px, in questo caso), in modo che questo browser renda il box delle stesse dimensioni di un browser standard.

Gli hack

Un box in un box

Il nome dice tutto. Rimuovete semplicemente il padding ed i bordi dal box incriminato, inserite un secondo box all'interno del primo e date a quest'ultimo il padding e i bordi insieme con il contenuto. Fine del problema. L'unica controindicazione è che questa soluzione viene realizzata con la marcatura e non con i CSS. Molte persone la considerano una brutta soluzione, perché a distanza di anni, quando non c'è più bisogno di un hack con i CSS, un hack con i fogli di stile si rimuove rapidamente, mentre gli hack con la marcatura sono sparsi dappertutto. In più complica la marcatura, strutturalmente parlando.

Assomiglia a questo, se state usando due div:

div { width: 100px; }
div .i { padding: 1em; }

<div>
 <div class="i">
  Testo
 </div>
</div>

Se viene usato con due elementi annidati, l'unico effetto negativo di questa soluzione (un solo div extra nella marcatura) è un falso problema. Il beneficio maggiore di questo metodo è che funziona dappertutto.

L'hack di Tantek

L'hack di Tantek Çelik è un ingegniosa soluzione per gestire l'errata interpretazione di Internet Explorer 5 del box model. Si basa su un bug nel parsing di Internet Explorer.

Si veda http://www.tantek.com/CSS/Examples/boxmodelhack.html

Il box model hack semplificato (SBMH)

Questo hack fu spiegato per la prima volta in un superbo [post] da Andrew Clover di CssDiscussList. Anch'esso sfrutta il bug nel parsing dei caratteri di escape, come l'hack di Tantek, ma qui viene usato direttamente su una proprietà invece che nel mezzo delle dichiarazioni.

La struttura di base è questa:

div {
width: 100px;
}
div {
\width: 140px; 
w\idth: 100px;
}

La prima regola (riga 1) viene usata dai browser come Opera 5 per usare il box model corretto, ma poi viene nascosta dagli escape nella regola che segue. Opera 5 ignora completamente queste regole.

La prima proprietà con escape (riga 5) viene usata da Internet Explorer 5.x, e da a questo browser un valore addomesticato. La seconda proprietà con escape (riga 6) non viene letta da Internet Explorer 5.x, ma viene usata dai browser moderni come Netscape 6, Mozilla, Opera 6 ed Internet Explorer 6.

Nota: Se Netscape 4 dovesse vedere anche uno solo degli escape, esso ignorerebbe l'intero foglio di stile. È quindi di importanza vitale che questo hack gli venga nascosto, o con @import o con il CaioHack. Per una spiegazione dettagliata del bug nel parsing degli escape si veda questo [post] di Andrew Clover.

Corretto uso degli escape: L'escape '\' con cui comincia la riga 5 deve sempre precedere la prima lettera del nome della proprietà. Internet Explorer 5.x/Win non ama gli escape, ma sembra ignorarli quando sono in questa posizione.

Importante! Un escape non deve precedere nessuno dei seguenti caratteri alfabetici: a, b, c, d, e, f, a causa della [compatibilità futura]. Se ciò dovesse avvenire, questi caratteri verrebbero interpretati come cifre esadecimali con brutte conseguenze. Ciò significa che una proprietà che inizia con una di queste lettere non può ricevere l'hack. Per esempio, 'height' può ricevere l'escape, ma 'font-family' no, dato che comincia con un carattere che viene interpretato come l'inizio di un codice esadecimale. Fortunatamente, né 'width' né 'height', che sono le proprietà più importanti per questo hack, ne sono influenzate.

Nella riga 6 (browser moderni) l'escape deve essere all'interno del nome della proprietà, e si applicano le precedenti regole per i caratteri esadecimali.

Un SBMH modificato (Tan hack)

Usando l'esempio precedente la sintassi di questo hack è la seguente:

div
{
  border: 10px;
  padding: 10px solid;
  width: 100px;
}

* html div
{
  width: 140px;
  w\idth: 100px;
}

La prima regola contiene il codice necessario per i browser che implementano correttamente il box model.

La seconda regola usa lo Star Html Hack. Poiché html è l'elemento radice, il selettore universale '*' non dovrebbe selezionare nessun elemento in un documento (X)HTML valido. Ma Internet Explorer (per Windows e per Mac) sembrano ignorare il selettore universale (asterisco) quando questo precede html. Lo stesso accade per * * body. Grazie a questa peculiarità possiamo di fatto nascondere un intera regola ai browser diversi da Internet Explorer.

La riga 10 viene letta da tutte le versioni di Internet Explorer. La riga 11, come spiegato in precedenza, viene nascosta ad Internet Explorer 5/Win a causa del carattere di escape. Explorer 5 Mac ed Explorer 6 Windows, che implementano il box model correttamente, ottengono quindi una larghezza di 100px.

Dato che il selettore universale su html non seleziona nessun elemento effettivo, i browser che hanno la fobia degli escape come Netscape 4 ed Opera 5 non leggeranno affatto il blocco di dichiarazione, e quindi sono di fatto protetti dagli escape.

Si tratta di una breve introduzione a questa tecnica. Una discussione più esaustiva è disponibile su [SBMH modificato]. Potreste anche voler [testare] la reazione del vostro browser all'hack. Nella pagina è compresa una tabella che riassume i risultati dei test sui browser. I test sui browser Mac sono molto richiesti.

Tre hack alternativi

Le tecniche che seguono si basano sul fatto che tutte le versioni di Internet Explorer/Win (e sfortunatamente anche Mac) hanno varie forme di [bug nei commenti], ossia, a seconda di dove venga posizionato il commento, una versione o l'altra di Explorer ignoreranno la dichiarazione in cui si trova il commento.

Ecco alcuni bug nei commenti che si possono usare negli hack:

Come negli hack visti in precedenza, le tre tecniche che seguono sono concepite per dare ad Internet Explorer 5.x/Win la larghezza complessiva del box, e la larghezza dell'area di contenuto agli altri browser.

Tecnica 1

Sintassi:

div
{
  border: 10px solid;
  padding: 10px;
  width: 140px; 
  width/* */:/**/100px; 
  width: /**/100px;
}

La riga 5 viene letta da tutti i browser. La riga 6 viene nascosta ad Internet Explorer 5/Win. Ma poiché c'è uno spazio bianco all'interno del commento adiacente alla proprietà 'width', Explorer 5.0/Win ignorerà anche la dichiarazione successiva. Perciò anche la riga 7 è nascosta. La riga 7 è nascosta anche ad Internet Explorer 5.5/Win a causa del commento adiacente al valore. Le righe 6 e 7 non sono nascoste ad Explorer 6/Win.

Tecnica 2

Sintassi:

div
{
  border: 10px solid;
  padding: 10px;
  width: 100px !important;
  width: 140px;
  width/**/:/**/100px;
}

La riga 5 viene letta da tutti i browser. Ma Internet Explorer/Win non implementa !important, così questo valore non sovrascriverà gli altri due. La riga 7 è nascosta ad Internet Explorer 5.x/Win, e quindi applicherà il valore dato alla riga 6. Internet Explorer 6/Win leggerà tutti i valori, ma applicherà solo l'ultimo (riga 7).

Tecnica 3

Sintassi:

div
{
  border: 10px solid;
  padding: 10px;
  width: 100px !important;
  width /**/:140px;
}

La riga 5 viene letta da tutti i browser. Internet Explorer/Win non implementa !important e quindi questo valore non ha importanza per questo browser. La riga 6 viene nascosta solo ad Internet Explorer 6/Win. Perciò Internet Explorer 5.x/Win e ogni altro browser che non implementa correttamente !important otterranno una larghezza di 140px.

Nota importante: L'ordine delle varie dichiarazioni di larghezza è fondamentale. Devono comparire come mostrato nelle precedenti tecniche, o gli hack falliranno. Tuttavia altre dichiarazioni (come 'background-color', 'font-size', 'position', ecc. ) possono comparire prima e dopo di queste.

Come avrete notato, queste tre tecniche ovviano al bisogno di due insiemi di regole, semplificando così il foglio di stile.

Si tratta di un'introduzione molto breve a tali tecniche. Una discussione più esaustiva si trova presso la [pagina dei box model hack alternativi]. Potreste anche voler [testare] come il vostro browser reagisce agli hack. Nella pagina si trova una tabella che riassume il risultati dei test nei browser.

Qual'è la conclusione?

E cosa otteniamo quando facciamo un riassunto di tutto questo? Non ne sono molto sicuro... qualcuno di voi?

L'hack di Tantek
In genere funziona, ma è complicato da inserire. E influenza anche Internet Explorer 4 e Netscape 4 che non ne hanno bisogno.
SBMH
Funziona, ma colpisce fatalmente Netscape 4 disabilitando l'intero foglio di stile. Influenza anche Opera 5 e Konqueror.
SBMH (Tan hack)
Anche questo funziona, e non colpisce Netscape 4. Lo svantaggio sta nel dover specificare la proprietà width tre volte per farlo funzionare, e due di queste in una regola separata.
Hack alternativi, 1-3
È questa la soluzione definitiva? Colpisce Konqueror su Linux, e qual'è la differenza e dove non funzionano? Sembra che la Tecnica 3 sia una buona soluzione, ma è la soluzione definitiva? In Netscape 4.8 tutti i box vengono spezzati in piccoli box attorno ciascuna parola.

Così resta la domanda: quale hack usare contro il box model errato di Internet Explorer 5/Win? Quale hack ha il minor numero di effetti collaterali?

Un'altra soluzione di Tantek

Un altro modo per risolvere il problema del box model errato di Internet Explorer 5.x/win è il Mid Pass Filter (http://www.tantek.com/CSS/Examples/midpass.html). Questa sembra essere la soluzione migliore, poiché non ha effetti collaterali in altri browser. In più separa gli hack dal codice normale.

div {
border: 10px solid;
padding: 10px solid;
}

@media tty {
 i{content:"\";/*" "*/}} @import 'midpassbefore.css'; /*";}
}/* */

div {
width: 100px;
}

@media tty {
 i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
}/* */

midpassafter.css contiene:

div {
width: 140px;
}

Il box model hack CSS3

div::outside { width: 100px; }
div { padding: 20px; }

Usare codice proprietario o anche le soluzioni con un box in un box

Ci sono altri modi per risolvere il bug evidenziati di seguito:

[Alternative agli hack del box model]

[Hackerare il box model usando PHPSS]