Browsers: Box Models, fouten en oplossingen
Met de publicatie van CSS1 in 1996 stelde het W3C voor om elk object op een webpagina in een kader te plaatsen, dat dan door de ontwerpers kon worden beheerd door het toevoegen van regels in het CSS bestand.
Het speelt geen rol of het object een paragraaf is, een lijst, koptekst, afbeelding of generisch block-level element zoals <div id="navigation">. Als het op een website kan worden geplaatst via opmaak, dan zal het in een kader geplaatst worden.
Hoe het Box Model werkt
Volgens CSS zijn er dus 4 gebieden (content, padding, border en margin) dewelke allemaal een waarde kunnen krijgen. Deze waarden zijn allemaal additief. Om de totale breedte van een kader te bepalen moeten dus de waarden van de vier gebieden bij elkaar opgeteld worden. Stel dat de content een breedte heeft van 400px, een padding 50px aan elke kant en de rand 2px bedraagt. Dit zou betekenen dat de totale breedte 504px bedraagt (400 content + 2 linkerrand + 50 linker padding + 50 rechter padding + 2 rechterrand = totaal van 504).
Hoe het Box Model het begeeft
Bij de allereerste CSS toepassingen zoals die in IE4 tot IE5.5/Windows begeeft het Box Model het. In deze browsers, alsook in de IE/Mac voor versie 5.0 worden de waarden voor de breedte en hoogte die voor het content gebied bedoelt zijn toegekend aan de gehele box (exclusief de marges).
Volgende figuur toont het gebrekkige Box Model in actie. Laat ons het vorige voorbeeld eens bekijken in IE4-5.5/Windows. Als de content een breedte heeft van 400px, padding 50 aan ieders zijde en een rand van 2px, dan zal de totale breedte nog steeds 400px zijn in plaats van de correcte 504px. Het content gebied zal samengedrukt worden tot 296px (400 - 50 - 50 - 2 - 2). Hoe groter de padding en border waarden, hoe verder de lay-out zal afwijken van je oorspronkelijk ontwerp en hoe meer het content gebied zal samengedrukt worden.
Honderden miljoenen mensen gebruiken nog steeds IE5.x/Windows, en tienduizenden ontwerpers hebben reeds het foutieve Box Model geleerd en gebruikt in hun designs. Hierdoor worden verscheidene lay-outs verkeerd weergegeven in browsers die het Box Model correct interpreteren (zoals IE6/Windows, IE5/Macintosh, Netscape 6 +, Mozilla, Chimera, Safari, Opera 5+,...)
Er bestaat echter een oplossing voor dit prangend probleem ? meer zelfs, het kwam van een ingenieur van Microsoft.
Verdediging van het gebrekkige Box Model
Het box model in IE4/5.x/Windows (en in alle IE/Macintosh versies voor 5.0) is zonder enige twijfel foutief volgens de CSS specificatie, maar toch is het niet dom. In sommige situaties is dit box model eenvoudiger in gebruik en praktischer dan de werkelijke CSS specificatie. Het CSS box model werkt goed wanneer er lay-outs moeten geproduceerd worden met absolute pixel waarden, maar het kan problemen en frustraties veroorzaken wanneer men een lay-out probeert samen te stellen via percentages (zogenaamde 'liquid design') om het ontwerp aan de schermgrootte aan te passen.
Onder het foutieve box model van IE4/5/Windows is het eenvoudiger om dus liquid designs te produceren, die een combinatie gebruiken van lengte en percentage waarden, zonder het nodeloos nesten van divs. Hiermee wordt niet gezegd dat IE4/5/Windows de belichaming was van onderdanigheid aan standaarden, want dat was het zeker niet. Maar toch moeten we toegeven dat ook dit gebroken model zijn voordelen had.
Box Model Hack
Het was Tantek ?lik die met een oplossing voor het probleem voor de dag kwam. Hij maakte hiervoor gebruik van een CSS parser bug in IE5.x/Windows om een valse waarde aan IE5.x/Windows mee te geven en deze dan te overschrijven met de correcte waarde.
De correcte waarde voor het content gebied is 300 pixels, maar IE/Windows interpreteert het verkeerd door 100 pixels aan padding en borders af te trekken.
Hier is de CSS regel voor alle normale browsers:
div.boxtest {
border: 20px solid;
padding: 30px;
background: #ffc;
width: 300px;
}
Browsers die het box model correct interpreteren zullen een kader aanmaken waarvan de totale breedte 400px bedraagt (20 + 30 + 300 + 30 + 20 = 400). Verouderde versies van IE/Windows zullen de totale breedte dus beperken tot 300px en de content verkleinen tot 200px. We kunnen dan 2 regels toevoegen aan ons CSS klasse.
div.boxtest {
width: 400px;
voice-family: "\"}\"";
voice-family: inherit;
width: 300px;
}
IE5.x/Windows stopt met het lezen van de CSS klasse wanneer het bij de voice-family regels komt die hij niet verstaat. Andere browsers lezen wel nog verder, waardoor ze toch nog de correct waarde krijgen.
Opera browsers (diegene voor versie 7) hebben dan nog een bijkomend probleem. Zij verstaan wel deze CSS2 selectors, maar kennen dezelfde CSS parsing bug als IE/Windows. Dus Opera zou ook diezelfde waarde kunnen aannemen, hetgeen niet de bedoeling kan zijn. Tantek heeft dit opgelost door een bijkomende regel toe te voegen:
html>body .content {
width: 300px;
}
Deze CSS regel is van hogere prioriteit dan de vorige regels en zal de andere regels overschrijven.