Box Model e workaround

Lunedì 19 Settembre 2005 - 08:45

di Alessandro Fulciniti

CSS

Uno dei miei primi articoli su PRO, che risale a circa due anni fa, è quello sul box model. Ho pensato di proporre su questo blog un post su una delle tecniche che non è presente in quell’articolo, una tecnica di facile applicazione, solida, robusta e a prova di futuro.

Rivediamo brevemente il problema: se assegniamo una larghezza esplicita a un elemento, secondo le specifiche CSS questo valore indicherà l’area utile al contenuto, bordi e padding esclusi. Internet Explorer 5.0, 5.5 (e la versione 6 in quirk mode, ovvero senza un corretto doctype), interpreteranno tale valore come
la larghezza totale dell’elemento, includendo erroneamente, quindi, bordi e padding. Per ottenere un dimensionamento consistente le possibili soluzioni sono due:

  • Evitare di specificare la larghezza effettiva all’elemento e insieme bordi e/o padding
  • Usare uno delle tante versioni del box model hack

La prima soluzione è adottabile in casi semplici, ma il più delle volte tende a complicare le cose:
infatti per ogni elemento figlio diretto del contenitore a larghezza specifica dovremo indicare padding
e/o bordi orizzontali.

Ora vediamo come costruire la soluzione con il box model hack. Molte delle versioni dell’hack sono semplicemente inspiegabili da un punto di vista logico, e difficili da ricordare. La versione che vedremo qui è a mio parere la più logica e semplice.

Normalmente tra due dichiarazioni in cui sono in gioco la stessa proprietà, a prevalere è l’ultima. Vediamo un piccolo esempio:


p{
color: blue;
color: green}

Quale sarà il colore del testo dei paragrafi? Sarà verde in tutti i browser dato che il colore
verde viene specificato come ultimo in ordine di codice. Ora, la parola chiave !important è in grado di dare una maggiore priorità ad una dichiarazione. La seguente regola:


p{
color: blue !important;
color: green}

darà un testo blu in tutti i browser aderenti alle specifiche CSS2. Internet Explorer, versione 6 inclusa, non dà la priorità alla keyword !important, facendo si che il testo sia verde.
Ora spostiamoci sulle dimensioni. Vogliamo ottenere un elemento con larghezza totale di 200 pixel e larghezza effettiva di 180px, con 10px di padding sui lati.


div#box{
width: 180px !important;
width: 200px;
padding: 0 10px}

Nei browser recenti (Opera, Mozilla, Firefox e Safari) che interpretano correttamente il box model
e la keyword !important abbiamo ottenuto il dimensionamento voluto. Per Internet Explorer 5.x ci siamo: viene servita una larghezza totale di 200px.

Abbiamo ancora un problema: IE6 aderisce alle specifiche CSS per le dimesioni, e così abbiamo risolto
il problema su IE5.x per spostarlo su IE6. Questo browser infatti vedrà i 200px come larghezza
utile al contenuto, e otterremo quindi un box con 220px di larghezza totale.

Per sistemare le cose, basta un commento vuoto (prima dei due punti, e anticipato da uno spazio) per nascondere la seconda dichiarazione a IE6, che verrà comunque interpretata da IE5.x. Vediamo così la versione definitiva:


div#box{
width: 180px !important;
width /**/: 200px;
padding: 0 10px}

Abbiamo così ottenuto un dimensionamento consistente in tutti i browser in sole due dichiarazioni. C’è una cosa da notare: la tecnica di per sè non è un vero un proprio hack. Diciamo che è un hack parziale, solo per IE 5x, che non aderisce alla specifiche riguardo la parola chiave !important, e per IE6 che non legge il valore dopo il commento vuoto. Dietro comunque c’è una logica a sostenerla, che funziona nei browser attuali e dovrebbe garantirci che i browser futuri interpreteranno correttamente.

La tecnica ci consente di usare il box model hack anche nei rari casi in cui vorremmo stabilire un’altezza specifica, ecco l’esempio di un div con bordi e padding:


div#box{
height: 180px !important;
height /**/: 200px;
border: 5px solid #CCC;
padding: 5px}

Volendo si possono impostatare anche altezza e larghezza nella stessa regola.

Un’altra applicazione utilissima potrebb essere per la creazione di dichiarazioni specifiche per IE e per gli altri browser. Per esempio, dato che IE fino alla versione 6 non supporta le PNG trasparenti, potremo servigli una GIF. In questo caso il commento vuoto viene omesso, dato che vogliamo che la gif venga servita anche a IE6:


div#box{
background: url(shadow.png) !important;
background: url(shadow.gif)
}

Lo stesso approccio può essere usato per risolvere alcuni bug di IE, e in particolare il Peekaboo bug, ottenendo una versione un po’ più pulita dell’Holly Hack:


div#box{
height: auto !important;
height: 1%}

Questo è tutto Due approfondimenti in merito sono la serie di tre articoli sulla risoluzione dei problemi nella sezione CSS di PRO (primo, secondo
e terzo) e il mio articolo
in inglese CSS design for the future.

Tags:

Categoria: CSS | Permalink

Commenti

1

Articolo molto interessante, finalmente una soluzione semplice e pulita a questo problema che ho dovuto affrontare diverse volte.

# - postato da francesco - 10 Novembre 2006 - 10:06

2

Grazie Francesco. Mi capita spesso ultimamente di riferirmi a questa pagina dagli articoli di html.it e devo dire che è davvero preziosa.

Ne approfitto per un piccolo aggiornamento: i metodi presentati qui sono totalmente compatibili con IE7, dato che il nuovo browser di casa microsoft obbedisce alle specifiche CSS e alla keyword !important.

Tra le altre cose il commento vuoto prima dei due punti non ha più effetto in IE7; IE7 ha poi il supporto delle PNG, quindi è valido anche l’esempio riferito alle immagini.. è valido anche quello relativo all’holly hack.

In sostanza per il lavoro di fino per IE5.x e IE6 l’approccio con l’!important e dove serve il commento vuoto, si rivela la migliore soluzione attualmente. E il fatto che IE7 non soffra più di molti bug di IE6 ci dovrebbe far star tranquilli e assicurarci che la tecnica è a prova di futuro.

# - postato da Alessandro Fulciniti - 11 Novembre 2006 - 00:06

3

Io è da molto che uso questa techica, sopratutto con le altezze delle pagine :) non sapevo si chiamasse così :)
Buono a sapersi

# - postato da lordmarin - 14 Febbraio 2007 - 11:34

4

Inanzitutto volevo ringraziare, stavo cercando proprio questo genere di walkaround senza dover richiedere l’interpretazione del browser da tecnologie serverside. Davvero ottimo!

Piccolo appunto: le PNG trasparenti NON sono supportate nemmeno da Explorer 6. Supportano un solo colore ALPHA (100%) ma non hanno un canale aggiuntivo ALPHA [0-100]% per ogni colore dichiarato. -> Addio effetti di trasparenza :(

Max

# - postato da Max - 06 Marzo 2007 - 16:07

5

Max, grazie per i complimenti. In quanto a IE6 e alla trasparenza PNG nel tuo appunto: infatti ho scritto che IE fino alla versione 6 non supporta le PNG trasparenti.

# - postato da Alessandro Fulciniti - 06 Marzo 2007 - 18:57

6

Grazie Alessandro per l’ottimo articolo. Vorrei sottoporre questa versione alternativa dell’hack del box model per IE5.x:

#box {
	border: 10px solid #00FF00;
	padding: 20px;
	width: 100px;
	height: 100px;
	/*width: 160px;*/
	/*height: 160px;*/
}
contenuto

In pratica le proprietà per IE5.x vanno messe in fondo alla regola, commentate singolarmente e poi fatto l’escape degli asterischi.
Non ho avuto molto tempo per testarlo, ma l’ho già provato, e funziona, sui seguenti browser e piattaforme:

IE 5.0/Windows
IE 5.5/Windows
IE 6.0/Windows
IE 7.0/Windows
Firefox 2.0/Windows
Opera 9.10/Windows
IE 5.2/Mac
Opera 8.51/Mac
Netscape 7.2/Mac
Firefox 2.0/Mac
Safari 1.3.2

# - postato da Maurizio Treppo - 07 Marzo 2007 - 02:04

7

Maurizio, vedi.. ci sono due classi di hack: quelli che fanno leva sulle mancanze di supporto o aderenza dei CSS del browser da una parte e quelli che fanno leva sui rendering engines e i parser dall’altra. L’uso della keyword !important appartiene al primo tipo (a parte il commento vuoto che serve per IE6) e ci dovrebbe garantire che l’hack (o workaround che dir si voglia) funzionerà anche in futuro.

La soluzione da te proposta appartiene invece alla seconda classe, e soluzioni di questo tipo si rivelano a parer mio più instabili in quanto, mentre è auspicabile che i browser aderiscano alle specifiche CSS, non è prevedibile nè sicuro di come possano reagire a sequenze di caratteri inaspettati e/o imprevisti nelle versioni a venire. Inoltre, non passa la validazione. In sostanza: un bel tentativo… ma non me ne volere, ne sconsiglierei l’uso.

# - postato da Alessandro Fulciniti - 07 Marzo 2007 - 21:35

8

Grazie Alessandro, concordo, ho avuto un po’ di tempo in più per fare altre verifiche e non vale la pena di usare la mia proposta, molto meglio !important e /**/.

Ho verficato inoltre che con IE per Mac (versione 5.2.3) non ha bisogno dell’hack, e supporta perfino le PNG con trasparenza. Certo IE per Mac ha altri difetti, ma sembra battere le versioni 5.x di Windows. Mi chiedo con che criterio quelli di Microsoft hanno realizzato IE 5 per le due piattaforme, sembrano quasi fatti da due team diversi… :-)

# - postato da Maurizio Treppo - 30 Marzo 2007 - 14:12

9

Articolo utilissimo,grazie molto per il suggerimento!cercavo propio questo attributo “salva-visualizzazione”.

# - postato da federico - 03 Aprile 2007 - 23:48

10

Grazie mille per quest’articolo, era proprio quello che cercavo

# - postato da Angelo - 21 Maggio 2007 - 12:28

11

Tecnica a prova di futuro?
Qualcuno ha per caso idea di come si comporti
“width /**/: 200px;”
su internet explorer 8?

Secondo me commenti condizionali sempre!!!
Basta con workaround e hack.

# - postato da Grab - 13 Giugno 2007 - 08:57

12

Grab, ho usato il condizionale.. ma a parer mio non fa differenza che “width /**/: 200px;” venga letto da IE8 o no, dato che IE7 obbedisce alla keyword !important e prenderà l’altra dichiarazione per buona.

Se IE8 avrà aderenza maggiore o uguale ai CSS di IE7, la tecnica non dovrebbe dar problemi.

# - postato da Alessandro Fulciniti - 15 Giugno 2007 - 07:34

13

Ciao!
Anch’io uso sempre il hack “!important”.
Ho notato però che in un caso con IE7 non funziona: nel float.
All’interno di una complicata struttura ho due blocchi che voglio avere l’uno accanto all’altro e devo specificare float:left; per Explorer e float:none; per Mozilla.
Quindi scrivo:

float:none !important;
float:left;

Ebbene IE7 considera più importante il float:none, fregandosene della riga successiva.

C’è un workaround anche per questo problema?
Grazie
Nietta

# - postato da Nietta - 02 Agosto 2007 - 11:32

14

Nietta, il punto è che IE7 aderisce alle specifiche in merito a !important, quindi quello che succede in realtà è il comportamento atteso.

Potrebbe esserti utile una lettura all’articolo Hack per IE7 e la relativa Tabella di compatibilità.

# - postato da Alessandro Fulciniti - 02 Agosto 2007 - 19:06

15

Beh, è una tecnica utilissima! Risolve di certo una grandissima parte di problemi riguardanti i bug di IE…veramente fantastico.
Ne ho sesntito spesso parlare di questi hack, ma non sapevo come utilizzarli e a cosa servissero veramente.
Articolo illuminante!:-)

# - postato da Simone - 03 Settembre 2007 - 18:06

16

La mia lettura è tardiva, ma penso non sia mai troppo tardi per fare i complimenti. :)

Sono un programmatore embedded che per hobby si sta avvicinando all’web development, e ho trovato di chiarezza estrema questa soluzione a quello che è uno dei “barrè” del web design.

Grazie e… al prossimo articolo. ;)

# - postato da Roberto Caboni - 10 Febbraio 2008 - 20:28

Inserisci il tuo commento:





(puoi usare i seguenti tag HTML per formattare il testo -
a href, b, i, br/, p, strong, em, ul, ol, li, blockquote, pre):

 

Anteprima del commento