Anne van Kesteren

Box Model

The CSS box model is probably the most important thing you need to know about when you start learning CSS in more detail. The problem is that two versions of Internet Explorer for Windows, 5.0 and 5.5, implanted a wrong model. Therefore, (almost) every commercial site has at least one CSS hack, a box model hack, in order to work around the bug in those (still used) versions of Internet Explorer.

The official box model, as defined by the W3C in CSS1, calculates the total width of a block-level element in the following way (quote from CSS2, since CSS2.1 is not yet a recommendation and CSS2 defines this better than CSS1):

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right'

Internet Explorer (version 5.0 and 5.5 for Windows) does this different. It is quite important to know that Internet Explorer version 6 for Windows in quirks mode rendering handles the box model exactly the same as the older versions of Internet Explorer. You can switch IE into quirks mode by adding a line of code before the document type declaration, like a comment or an XML Prolog Declaration. However, using an XML Declaration or processing instruction is not recommendable, since some browsers, like Internet Explorer 4 for the Macintosh, will crash:

IE4.x/Mac will render a blank page when it encounters the XML-prologue at the top. A HTML comment instead does fine to put IE6 into quirks mode.

How the older versions of Internet Explorer handle the box model:

'margin-left' + 'width' + 'margin-right'

The "W3C box model" was designed with HTML in mind. For example: the IMG element. This is a inline, replaced element, so the box model applies to this element as well (note that the IMG element should have display:inline-block; as default style declaration (when the image is found), not display:inline;). The IMG element has a default height and weight, so how does Internet Explorer handles padding on that element (it doesn't) or a border. When you apply a border property to the IMG element Internet Explorer (5, 5.5 and 6.0 in quirks mode for Windows) "modifies" its box model to:

'margin-left' + 'border-left-width' + 'width' + 'border-right-width' + 'margin-right'

That doesn't make sense, does it? Another example why the W3C box model is "better" are form elements. Think a moment about this example: input[type=text]{height:1em;}. Done? Let's continue.

Now you know what the problems are, you probably want to workaround those to fix your layout and make it work in every browser. There are plenty of CSS filters available, I will highlight some.

Probably the most well known hack is simply called Box Model Hack. To use this, you'll have to make sure Internet Explorer 6 for Windows renders in standard-compliant mode, otherwise it will switch to the "IE box model" and the sky will fall on your head.

Personally, I like a smaller version of that hack, which requires that IE6 renders in quirks mode. You might find it odd to set Internet Explorer in quirks mode, but it will not affect your pages, since, for commercial sites, it has to work in older Internet Explorer versions as well (or not?). How to use it:

element{
 border:20px solid #000;
 padding:30px;
 background:#ffc;
 width:400px;    /* IE width */
}
parent>element{  /* Make sure there aren't any spaces within the selector! */
 width:300px;    /* Correct width */
}

If the element is a DIV with an ID set to 'content' and it is a direct child of the BODY element the first selector becomes div#content and the second body>div#content. The last hack is frequently used, unfortunately (I see it quite a lot at forums). The hack uses an implementation in Opera, IE5 Macintosh and Mozilla (using a -moz- prefix as defined by CSS2.1) (Safari?) based on CSS3 to switch to the "IE box model". If you want the hack to apply to all elements, you could use:

*{
 box-sizing:border-box;
 -moz-box-sizing:border-box;
}

I dislike this method, since both specifications it is defined in are not yet candidate recommendations (css3-ui, css3-box; eventually, it will be part of css3-box) and because I think that the W3C box model makes more sense, as explained above.

Comments

  1. I've been using a javascript to recalculate the old IE box when needed. It seems to work, I haven't run into any real problems yet.

    Yes I know, it's not the prefered methode, especially when users have javascript turned off it becomes kind of pointless. Using one technology to fix another is asking for it. But hey, it's my blog so I don't mind so much in this case. :)

    Posted by Egor Kloos at

  2. input[text]{height:1em;} should be input[type="text"]{height:1em;}

    Anne: fixed, without unnecessary punctation marks.

    Posted by liorean at

  3. -moz-box-sizing only works in Gecko browsers. I don't know any implementation that might work in Safari; prefixing with -khtml certainly doesn't work. Plus, you have to send IE6 into quirks mode for it to work there (and that makes it even more buggy, imho).

    Posted by Philippe at

  4. I agree on the fact that people should know about the correct box model, and the fact that IE versions <6 implement it incorrectly. IE6 in standards compliance mode, however, does get it right.

    I know we've had this discussion IRL already, but I like to state it once again.

    As Philippe correctly points out, IE6 in quirks mode does not give us the improved support for standards. I know, it is not at the level it should be, or most of us want it to be, but it is better that the quirks mode and therefore more predictable. If you revert to a hack to satisfy IE, then why not exclude IE6? There are hacks that apply only to IE<6, why not use those? One example is the so called Highpass Filter as described by Eric Meyer.

    IMHO it is hypocracy to force IE6 into quirks mode just because it makes things easier for you. Once you make the decision to use hacks, you should use those that take full advantage of the improved IE6 CSS support. We don't want IE6 to become like Netscape Communicator, do we? And in time - a few years or so - the number of users browsing with older versions will have become close to the numbers currently seen with Netscape Communicator.

    In short: why does someone who wants IE to support the standards force this very same browser to use the buggy parser. Personnaly, I don't get that. We should discuss this once more!

    Just my 2 cents... :D

    Posted by Basje at

  5. For the child selector rule, I prefer to use html>body element instead of parent>element as the selector. That way I don't have to know what the parent element is and it won't break if I move the element to a different parent. body will (should) always be the child of html.

    Posted by chris at

  6. I use the child-selector method as well, but prefer simply adding "*>" before my selectors. It works miracles, and makes your CSS so much clearer.

    However there is one problem browser - IE5.0:
    http://web-graphics.com/mtarchive/001142.php

    I've yet to think of a way around that.

    Posted by Stephen at

  7. @chris and Stephen, both your methods are indeed easier, but as Stephen already pointed out, IE5.0 for Windows gives problems, and I don't like that :-)

    Posted by Anne at

  8. I agree that for IE6 it is better to use a standards compliant mode. That only leaves us with box model differences for IE5/WIN, which hopefully will leave the browser arena in the next year or so.

    My favourite workaround is the box-model-hack. To some people it seems ugly, but it serves its purpose: clean up the mess that IE5/WIN makes. It is valid css and most important, it is transparent. If I see it I know why it is there for and so will my collegues. If some day in the future I decide to remove some IE5 specific code, I know where to find it. So a good argument for using it is consistency and keeping your designs simple.

    Another workaround I sometimes use is the box in a box, border and padding in the outer box and width in the inner one. It maybe looks less nice, because it requires more markup, but can be useful in cases where you don't want to be bothered to calculate the size differences.

    Posted by Bobby van der Sluis at

  9. Stephen and Anne, IE5.0 does indeed seem to apply declarations defined with a child selector - sort of. It seems to ignore the > and assumes a simple descendant relationship. But it will only do this if it can see the boundaries of the >. For instance, if there is whitespace on either side of the > or if the second selector (the child) is an id or a class. If you remove the spaces on either side of the > and use tag selectors, IE5.0 will ignore the rule. This is the beauty of using html>body element - it will be ignored by IE5.0 because it can't see the boundaries on the selectors. As an aside, one of the reasons why you don't run into this problem when using the traditional Tantek box model hack is because IE5.0 will ignore the rule that immediately follows the rule that contains the voice-family declaration with the } in it.

    Posted by chris at

  10. I'd like to mention the Tan hack. It targets all IE browsers (including Mac). If anyone has missed it, it looks like this:

    * html selector { rules }

    Combined with escape hacks and comment hacks, it is possible to target individual IE versions independently within this hack.

    My preferred method is to relegate those hacks to a separate CSS file, and include it via an IE-only conditional comment. Perfectly valid markup and CSS, and I don't burden good browsers with unnecessary junk.

    Posted by TOOLman at

  11. I use the "_something:" hack a lot nowadays.

    Posted by G. I. at

  12. But that hack is invalid... You could probably finde something better to use.

    Posted by liorean at