Come attaccare un bug di visualizzazione di IE (Win)

È un fatto risaputo che il browser Internet Explorer (per Windows) ha un'ampia varietà di bug di visualizzazione. Per quanto possa sembrare appagante criticare questo browser, IE è di gran lunga il più popolare browser sul Web, sicchè piagnucolare sui suoi errori non è di grande aiuto. È triste che molti autori che desiderano passare ad un design senza tabelle inizino con grandi speranze, solo per vederle infrante da quella che a volte è conosciuta come la "collezione di bug di Explorer".

Alcuni di questi bug non sono affatto "bug", ma piuttosto errate applicazioni degli standard W3C. Sebbene una totale comprensione di come IE "sbagli" sia un lavoro a tempo pieno, è possibile farcela con un minimo di strumenti per risolvere i bug, che è proprio quello che questo articolo vuole insegnarvi. Pronti? Via!

Prepararsi all'azione

Prima di risolvere qualunque bug, è necessario assicurarsi che il problema sia davvero un bug, e non un modo improprio di scrivere il codice o la mancata comprensione di come funzioni il posizionamento con i CSS. Come prima cosa nella caccia ai bug dovreste leggere Debugging CSS, the Easy Way, che descrive in dettaglio questa fase preliminare. Descrive anche il modo con cui creare un "caso-test minimale", che può semplificare di molto l'individuazione dei problemi.

Ma realizzare questo caso-test richiede tempo, e gli impegni di lavoro spesso impediscono alla gente di percorrere questa strada. Comunque sia, è un metodo da usare caldamente raccomandato, ed è quello che mettiamo in pratica regolarmente. Anche quando si è realizzato un caso-test, non è sempre facile dare solo un'occhiata e dire "Ah! Ecco qua!". Sebbene sia vero che avere una vasta conoscenza dei bug aiuti a localizzare un problema, molti sviluppatori impegnati non hanno tempo di dedicarsi allo studio esteso dei bug.

Tuttavia, una volta che si è preparato un caso-test minimale, di solito restano davvero pochi elementi della pagina da considerare, e diventa possibile sparare "pallottole magiche" a vari elementi nel tentativo di risolvere il problema. Sappiate comunque che queste soluzioni non servono contro qualunque comportamento corretto dei browser scambiato per bug dai principianti dei CSS. Tocca a voi avere una salda padronanza delle basi dei CSS. Sull'argomento potete leggere i seguenti articoli:

Le soluzioni da discutere sono inutili contro ogni deliberata violazione delle specifiche CSS che s'incontrano in IE/Win. Per saperne di più sulle errate applicazioni degli standard (che non sono bug), si legga:

Un problema speciale su cui è importante soffermarsi è il modo in cui i float vengono annullati col clear, come descritto nell'articolo "Float: The Theory" citato sopra. IE di solito consentirà (in modo errato) ad un contenitore di includere un float innestato, anche quando non è presente alcun elemento di clear. Questo crea l'impressione che i browser diversi da IE sbaglino, quando chi sbaglia veramente è IE/Win. Non fatevi ingannare così come molti altri. Potete trovare utili informazioni sui problemi minori di visualizzazione nella serie di articoli "Common Coding Problems" qui su CMX (una ricerca dei termini Common Coding Problems vi darà una lista di tutti gli articoli della serie).

Presupponendo che questi problemi siano stati ben compresi o che non siano rilevanti per il vostro attuale problema, andiamo a vedere proprio i metodi di risoluzione dei bug, va bene?

{ position: relative }

Questa "pallottola magica" è stata la prima ad essere scoperta nel lontano dicembre 2001 da un certo autore le cui iniziali sono "BJ" (ehm...). Comunque sia, il problema era una tecnica sviluppata da Eric Meyer qui, che sembra "perforare" un box fuori dell'angolo di un altro box. Il metodo di Eric consiste nel far fluttuare un box nell'angolo superiore sinistro di un elemento che contiene del testo, e poi nell'usare i margini superiore e sinistro negativi della misura di 1px, che ha l'effetto di "spingere" il float in alto e a sinistra di 1px.

Questo consente al float di coprire (o oscurare) i bordi di 1px del box contenitore in quell'area. Poi il float ottiene un bordo inferiore e destro che sembra essere parte del bordo complessivo. Fantastico! Il problema di questo metodo era che Explorer per Windows falliva nell'oscurare in maniera esatta il bordo dell'elemento grande, rovinando il previsto effetto "scatola perforata". Sembra che IE/Win abbia un problema quando un elemento è posizionato con i margini negativi fuori dal box genitore che lo circonda.

La porzione ancora all'interno del "contenitore" genitore è visibile, ma ogni altra parte che va oltre il limite interno del bordo del contenitore sparisce! Succede che, applicando un semplice { position: relative; } al box interno posizionato coi margini negativi, le porzioni mancanti riappaiono magicamente. Perchè? Bè, spostando a destra... seriamente, nessuno sa perchè questo accada, eccetto forse gli sviluppatori Microsoft (ma loro non parlano). Basti dire che funziona.

Presto si scoprì che questa soluzione funzionava anche su altri bug di IE, nello specifico il Peekaboo Bug in IE6. Torneremo sul Peekaboo Bug fra un pò. Un altro uso principale di questa soluzione ricorre quando un'immagine flottata è in un contenitore, ed anche il contenitore o l'immagine flottata è stata resa "relative". In questo caso, l'immagine flottata si "nasconderà" dietro ogni background posto sull'elemento contenitore esterno. Rimuovendo il posizionamento relativo o rendendo emntrambi gli elementi relativi, si riporterà l'immagine flottata "sul davanti", permettendo che sia vista.

Problemi con la soluzione "relative"

Di solito questa soluzione non influenza in modo sfavorevole gli altri browser ma, come è stato spiegato nel caso delle immagini flottate, può essere necessario adottare una "doppia" soluzione, usando due volte { position: relative; }. Capire dove applicare questa soluzione non è di solito un problema. Si deve solo applicarla ad un elemento per volta e vedere se il bug viene eliminato. Nel caso in cui questa soluzione causa dei problemi negli altri browser, si può nascondere, dandola solo a IE/Win con i metodi illustrati nella prossima sezione.

Soluzione dei bug dimensionali

Una percentuale molto alta di bug di IE/Win è causata dalla mancanza di dimensioni date per gli elementi che contengono float innestati. In altre parole, se avete un box senza una width o un'height e vi innestate uno o più float all'interno, possono presentarsi i bug di visualizzazione più strani. Tali bug possono verificarsi senza float, ma sono molto più rari della varietà di quelli col float. Il Peekaboo Bug ricade in questa classe di "bug dimensionali", come l' Escaping Float Bug. C'è di nuovo il Peekaboo Bug!

Così questo diavolo dalla scorza dura è vulnerabile sia alla soluzione con "relative" che alla soluzione dimensionale! Molto interessante. Tale è la natura della "scienza" dei bug di IE. Questa specie di "buggosità" di IE relativa alle dimensioni si conosceva da diversi anni, ma conoscerla soltanto non era abbastanza. Molto spesso non è desiderabile applicare una dimensione al box con bug. Usare una height è di solito inaccettabile, poichè l'altezza settata di default su auto permette al contenuto del box di determinare l'altezza verticale visualizzata del box.

Se date al box un'altezza definita, essa può non uguagliare l'altezza del contenuto, specie se il testo è complesso e l'utente cambia la dimensione del testo del browser. Una width a volte può essere usata, ma spesso il design della pagina richiede che il box in questione sia "liquido", così da allargarsi o restringersi automaticamente a seconda del variare della dimensione della finestra. Si, una larghezza in percentuale può anche farlo, ma cosa succederebbe se il box è una colonna centrale che ha bisogno di colonne laterali dimensionate in pixel accanto ad essa? È impossibile avere una larghezza in percentuale in un box e margini in pixel sullo stesso box, perchè nessuno può prevedere l'esito di un confronto fra pixel rigidi e percentuali fluide.

Chiaramente usare width come una dimensione per risolvere i bug è meno che soddisfacente. Non sembrava esserci un modo limpido di svolgere questo compito, ma, per uno strano scherzo del fato, lo stesso browser Explorer ci venne in aiuto.

Il trucco del box che si espande

I guru dei CSS sanno da tempo che quando IE/Win vede che un box ha una dimensione fissa che non è larga abbastanza da racchiudere il contenuto del box, il browser allargherà erroneamente l'ampiezza del box per farci entrare righe che non possono essere spezzate, come lunghi URL. IE/Win estenderà anche l'altezza di un box, così che il contenuto non fuoriesca oltre il bordo inferiore del box. I browser che seguono più strettamente le specifiche del W3C lasciano che il contenuto extra sporga oltre l'altezza o la larghezza del box.

L'Holly Hack

Poichè IE/Win sbaglierà in questo modo, quando c'è bisogno di una dimensione per risolvere un bug nel float, una piccola altezza, come { height: 1% }, si può applicare al contenitore del float, ed IE/Win renderà comunque il box più alto. Così una piccola altezza non cambia l'aspetto del box, ma IE sembra pensare che il box ora è "dimensionato", e così la nostra pallottola magica colpisce nel segno. Un bug in meno.

Dettagli dell'hack

Poichè gli altri browser non hanno il bug e, cosa più importante, non espandono erroneamente box definiti in altezza, questa altezza per risolvere i bug dovrebbe essere nascosta ai browser diversi da IE/Win. Non è necessario nascondere questa soluzione alle precedenti versioni di IE/Win, perchè sebbene non abbiano il Peekaboo Bug, hanno altri bug dimensionali e tutti applicano il trucco dell'espansione. Comunque, IE5/Mac non espande i box in modo scorretto, così far vedere a questo browser la piccola altezza di sicuro danneggia la sua visualizzazione.

Quindi l'altezza deve essergli nascosta, come per gli altri browser diversi da IE. Il codice seguente è un esempio dell'Holly Hack. Per prima cosa, l'Holly Hack consiste in un gruppo di metodi per nascondere messi intorno all'height 1%, che è la chiave dell'hack. Ricordate: l'idea è di far vedere ad IE/Win (e solo ad IE/Win) questa altezza e di applicarla al box con bug.

/* Nasconde da IE5-mac \ */
* html .buggybox {height: 1%;}
/* Fine per IE5-mac */

Due hack in uno: La prima riga del codice è un commento CSS con un "escape" (colorato in rosso) prima del tag di chiusura del commento. La presenza di un carattere di escape fa si che IE5/Mac ignori il tag di chiusura del commento, e pensi che il commento sia ancora attivo. Così ignora tutto finchè non vede quello che pensa sia un corretto tag di chiusura di un commento CSS. L'ultima riga dell'hack è un normale commento CSS, e il suo tag di chiusura è quello che fa iniziare a IE5/Mac ad interpretare di nuovo il codice.

Ci riferiamo generalmente a queste due righe (la superiore e l'inferiore nel codice di sopra) come al "Mac-hack", o meglio "comment-backslash hack". Il secondo (o riga di mezzo) ha, in questo esempio, tre voci separate da combinatori discedenti, che sono gli spazi che vedete, e quindi la proprietà height all'interno delle parentesi graffe. La prima voce è un selettore universale (o stella, *), che seleziona ogni elemento, seguito da html (entrambi in rosso), seguito dall'elemento sospettato di avere il bug. Il codice di sopra seleziona un elemento con l'attributo di classe buggybox, che è un discendente di un elemento html (il che sarà sempre vero), quando lo stesso html è discendente di ogni elemento (*), e applica una { height: 1% } a questo elemento (in questo caso .buggybox).

Accade così perchè tutti i browser IE, sia Win che Mac, riconoscono un invisibile e misterioso elemento contenitore intorno ad <html>. L'uso del selettore universale che precede html, conosciuto anche come Tan Hack (o Star HTML Selector Bug), funziona nei browser IE e in nessun altro. Sicchè il motivo per usare il "Mac-hack" è di impedire che IE5/Mac veda l'altezza come gli altri browser, dato che non allarga erroneamente il box come IE/Win, ma gli fa leggere il Tan Hack.

Si noti che l'elemento a cui va data l'altezza non ha bisogno di una classe. Ogni valido selettore può essere inserito al posto di .buggybox, e si possono usare anche intere stringhe che usano combinatori discendenti. La cosa davvero importante è che * html deve sempre precedere qualunque elemento da fixare, e che * e html hanno uno spazio fra loro, seguito da un altro spazio, e poi l'elemento. Ci sono altri metodi che possono essere usati per dare ad IE/Win l'altezza corretta di cui ha bisogno, senza darla agli altri browser.

Un metodo è impostare la piccola altezza nel selettore regolare per l'elemento, e poi sovrascrivere questa altezza col valore auto in un successivo selettore che usa un combinatore figlio ( > ), che IE/Win non riconosce. Ciò richiede la conoscenza del genitore diretto del box con bug. Non è una buona idea usare spazi attorno al combinatore figlio, perchè può provocare bug. Un altro metodo è usare il Tan Hack per nascondere l'altezza ai browser diversi da IE, e poi sovrascrivere questa altezza solo per IE5/Mac, usando una versione modificata per Mac del Tan Hack, che di nuovo usa il combinatore figlio per impedire ad IE/Win di leggere il valore ridefinito.

La versione Mac richiede un carattere di escape (un backslash, \), da usare in ogni nome di proprietà incluso in un gruppo di regole per impedire ad IE5/Win di leggere le regole. Nella versione del Tan Hack modificata per Mac, il combinatore figlio rimpiazza il combinatore discendente normalmente usato fra la stella (*) e html. Ciò è mostrato in rosso nell'ultima riga sotto. L'escape (il carattere backslash, anch'esso in rosso) è usato nella proprietà height. Entrambi i metodi alternativi appena descritti sono mostrati nel seguente codice.

Sovrascrittura col combinatore figlio
.buggybox {height: 1%;}
#parentElement>.buggybox {height: auto;}

Tan Hack modificato per Mac
/* per IE/Win */
* html .buggybox {height: 1%;}
/* per IE5/Mac */
*>html .buggybox {he\ight: auto;}

Quale metodo scegliere? Bè, come con la maggior parte delle cose relative ai CSS, dipende. Delle tre opzioni presentate, quello che useremmo con meno probabilità è il metodo di sovrascrittura col combinatore figlio. Preferiamo avere il selettore originale per un elemento che contiene il corretto valore per le proprietà definite al suo interno, e usare un hack (o filtro, come vengono chiamati a volte), per fornire valori alternativi ad IE/Win. Gli altri due metodi derivano da una questione di preferenze.

Nota: Il metodo di sovrascrittura col combinatore figlio è il nome che abbiamo dato al metodo descritto nel codice di sopra. Per quel che sappiamo, non c'è attualmente alcun nome usato per questo metodo, nè per la versione del Tan Hack modificato per Mac. Sappiate comunque che se una futura versione di IE/Win supporterà alla fine il combinatore figlio, questo hack può ritorcersi contro di noi, facendo vedere ad IE/Win l' "errato" valore dell'altezza, a seconda di quali cambiamenti possono verificarsi in questo browser.

Uso dei trucchi

Per quanto avere un "caso-test minimale" per provare queste soluzioni sia il metodo migliore, a volte è possibile per uno sviluppatore CSS saltare questo passo ed applicarle direttamente alle parti di una grande pagina complessa nella speranza di "avere fortuna". Questo approccio può essere comunque problematico per i principianti, poichè quello che può sembrare come un bug è spesso un comportamento corretto, o una violazione delle specifiche di IE/Win. Una buona regola (a lume di naso) è comparare la visualizzazione di un sospetto bug di IE/Win con la visualizzazione in Opera 7 e in un browser basato su Mozilla.

Se entrambi questi browser visualizzano bene, allora è sicuro che state vedendo un bug di IE o un comportamento scorretto. Riconoscerlo è un'altra faccenda, che richiede la conoscenza del modello float di IE, del box model di IE, del problema dei 3px di IE e a volte anche d'altro. Queste due "pallottole magiche" possono fare meraviglie, mettendo gli autori in condizione di utilizzare molti layout che in precedenza erano fuori portata a causa dei bug di IE. Non ci sono affatto panacee, per quanto a volte possa sembrare così, e certamente non vi sono sotituti per le giuste pratiche di scrittura del codice. Sebbene vi siano altre soluzioni non descritte qui, quelle di cui abbiamo parlato sono le principali armi in uso oggi per eliminare i bug nei design complessi senza tabelle. Un recente (e pieno di trucchi) layout col float usa ben otto Holly Hack per forzare "quel browser" verso la conformità. Bang! Bang!

di John Gallant e Holly Bergevin