Internet Explorer and the CSS box model

One of the differences between Internet Explorer and standards compliant Web browsers that cause a lot of trouble for CSS beginners is the CSS box model. Since the box model is what browsers use to calculate an element’s total width and height, it is quite understandable that different browsers producing different results can be both confusing and frustrating.

How the CSS box model works has been explained by others many times already. Nonetheless I still see questions related to the CSS box model on forums and mailing lists, and frequently encounter sites that expect browsers to use Internet Explorer’s non-standard way of calculating box dimensions. That is why I have written this article, which to a large extent is a translation of an article I wrote for Swedish magazine CAP&Design earlier this year.

If you already know how the different box models work and how to handle Internet Explorer, there is nothing new for you here. If you get different box dimensions in IE and other browsers without knowing why, keep reading.

The CSS box model diagram

Here is a simple diagram showing how the dimensions of an element are related in CSS:

For the purposes of this article, all browsers handle the margin property the same way when calculating an element’s total width, so I’ll be concentrating on the padding and border properties.

The W3C Box model

First a look at the the W3C box model, which is used by all standards compliant browsers and by Internet Explorer 6 and later if the circumstances are right. In the W3C CSS box model a block level element’s total width is calculated using the following formula:

The same concept applies to height, but for the sake of simplicity I will only talk about width from now on.

The IE Box model

The IE Box model is similar except for one important difference: paddings and borders are not included in the calculation:

total width = margin-left + width + margin-right

This means that if the element also has horizontal padding and/or borders, the actual content area will shrink to make room for them.

IE versions

Versions 5.5 and earlier of Internet Explorer for Windows always use the IE Box model. What many do not seem to be aware of is that IE 6 and later use the W3C box model when in standards compliant mode. This is a good thing since it means that problems will only occur in IE/Win 5.5 and older, provided that you use a DOCTYPE that makes IE use standards compliant mode.

Attacking the problem

By making sure that IE 6 is in standards compliant mode, you only have to care about this whole thing if you still are concerned about your sites looking the same in IE 5.*/Win as in more recent browsers. If that includes you there are several ways of attacking the problem, listed here in my order of preference:

Avoid situations that cause problems

Insert extra markup

Use conditional comments

Use CSS hacks

Since the problems caused by the Box model differences are often only cosmetic, my personal preference is to simply not bother with IE 5.*/Win. Sometimes that isn’t acceptable and I have to use one of the methods I’ll describe here.

1. Avoid situations that cause problems

This is how I prefer to solve the problem. I simply avoid specifying both widthandpadding or border for the same element. This ensures that all browsers will use the same total width, no matter which box model they use.

Let me use an example to illustrate. The HTML used to mark up a list of news articles could look like this (simplified):

<div id="news">

<h2>News</h2>

<ul>

<li>

<h3>News article 1</h3>

<p>Lorem ipsum dolor sit amet</p>

</li>

<li>

<h3>News article 2</h3>

<p>Lorem ipsum dolor sit amet</p>

</li>

</ul>

</div>

To make the list 250 pixels wide with a one pixel border and 10 pixels of padding, you could use the following CSS:

#news {

padding:10px;

border:1px solid;

width:228px;

}

In standards compliant browsers, the total width will be 250 pixels (1px left border + 10px left padding + width + 10px right padding + 1px right border). In IE 5.5 and earlier, the total width will be 228 pixels since it doesn’t add paddings and borders.

So how can you avoid this? Let’s assume that the news list is in another container, for instance a sidebar:

<div id="sidebar">

<div id="news">

...

</div>

</div>

If that is the case you can set the width on that container instead:

#sidebar {width:250px}

#news {

padding:10px;

border:1px solid;

}

Since #news is a block level element it will automatically fill the entire width of its parent element, which in this case is #sidebar.

2. Insert extra markup

If you can’t use method 1, another method is to insert extra markup. Using the same example as previously, assume that #news is not supposed to expand to the full width of #sidebar. Specifying a width for #news to prevent that is a the scenario you want to avoid. A workaround is to change the markup to this:

<div id="news">

<div>

<h2>News</h2>

<ul>

...

</ul>

</div>

</div>

and use the following CSS:

#news {width:250px}

#news div {

padding:10px;

border:1px solid;

}

The outer element controls the width, and the inner element contains the border and padding.

It’s up to you to decide whether it is a reasonable compromise to add extra markup like this. It is obviously better if you can avoid doing so, but an extra div element doesn’t cause any other problems than increased file size and slightly reduced markup maintainability. It does not affect accessibility or how the document is presented with CSS off. Besides, having an extra element is necessary to create certain designs, so you may already have the markup you need.

3. Use conditional comments

If there is no suitable element that can be used to control the width and you can’t or won’t add extra markup, IE 5.*/Win needs to get a different value for width.

In my opinion, the safest way of doing that is to use conditional comments, which are comments whose content is only visible to IE/Win. In this case only IE below version 6 are supposed to get the contents:

<!--[if lt IE 6]>

<style type="text/css">

#news {width:250px}

</style>

<![endif]-->

If you choose to use this method I recommend moving all IE 5.*/Win specific CSS to a separate file and load it like this:

<!--[if lt IE 6]>

<link rel="stylesheet" type="text/css" href="/css/ie5.css">

<![endif]-->

This is a safe way of ensuring that only the browsers that need the modified CSS see those rules.

4. Use CSS hacks

Finally you can also use a CSS hack to supply modified values to IE 5.*/Win. I recommend avoiding CSS hacks as much as possible. Just like the name implies, these are hacks, and hacks that are based on undocumented errors in different browsers’ CSS parsing. Since many people still use CSS hacks I’m mentioning it anyway. I highly recommend that you consider other options before using them unless you know exactly what you are doing.

The simplest CSS hack for working around box model problems is The simplified box model hack, SBMH. Provided that the HTML is the same as in the first example, the CSS would look like this:

#news {

padding:10px;

border:1px solid;

width:250px;

w\idth:228px;

}

All browsers see and understand width:250px. IE 5.*/Win does not understand the next line, w\idth:228px, which all standards compliant browsers do. The result is that width is set to 250px in IE 5.*/Win and 228px standards compliant browsers, giving the list the same total width in all browsers.

Conclusion

As I have shown here it is possible to avoid or work around the problems caused by the different CSS box models. Which method you use will depend on the circumstances.

I should also mention that some time in the distant future, the CSS 3 `box-sizing` property will let you choose which CSS box model you want browsers to use. The W3C box model is called `content-box` and the Internet Explorer box model is called `border-box`. Being able to control this in all browsers is a good thing since each model has its pros and cons. However, browser support is currently too limited for this property to be of any practical use.

Hopefully none of this will be necessary in a couple of years. IE 7 was released in October 2006, and for every day fewer and fewer use the older versions of IE. It is already acceptable for some sites to hide all CSS from IE/5.* or to simply not care about the rendering differences.

I’ll leave it to you to decide when you can start hiding CSS from IE 5.*/Win.

Comments

Excellent article Roger. My preferred method of dealing is avoiding situations that will cause me grief. Perhaps this is related to that, but I would like to add one to your “Attacking the problem” list:

Let go and allow things to be as is. In other words allow for these differences in the design. Obviously this won’t apply to all situations — like a pixel-perfect layout — but it is another method of “Attacking the problem.” Not attacking it at all by allowing a less rigid styling that will look good no matter what box model is used.

Out of interest, why do you prefer adding extra mark-up to conditional comments?

I always insert an IE 5-specific stylesheet via conditional comments anyway to deal with IE 5’s different model for font sizes in tables. I stick any necessary box model fixes in there.

I prefer coding to the standards first, and keeping any browser-specific workarounds in obviously browser-specific areas, i.e. conditional comments. I just wish other browsers implemented them so that we could fix old Firefox bugs too.

Really nice article!
But perhaps it should be noted that the css hack isn’t supported by older versions of Opera, and therefore perhaps isn’t a good solution at all if you don’t extend it with some extra css?
Just learned from the article you refered to :)

As Mike I also prefer to just avoid getting into trouble with the box model-bug since I’m not getting paid for trying to hack IE’s bugs. :)

On the other hand, when a problem is unavoidable I usually use conditional comments instead of adding extra markup. The conditional comment just lets the IE users download the extra CSS file, leaving the other users unbothered.

Unfortunately I’ve had to work without standards compliant mode for the last couple of months, working on a Notes site; due to a bug with Notes you can’t properly declare the DOCTYPE - although someone on the Port 80 (AWIA) forum showed me a hack for that which I’m going to try implement in a Notes site redev next year - very much looking forward to it! IE FTL.

So what if like Nathanael you have to work with a system like Notes/Domino that doesn’t allow you to change the DOCTYPE to a standards compliant DOCTYPE? Even if you could change the DOCTYPE, you might not want to use a standards compliant DOCTYPE since Domino produces non-strict HTML. For instance it doesn’t end list items and sometimes puts in a the beginning of paragraph but doesn’t end it.

In this case all versions of IE use the Microsoft box model, but what to other browsers like Firefox, Safari, Camino or Opera do?

I mostly go with Mike Cherim’s solution. As long as there is no breakage, I don’t worry about a bit of distortion.

But, I will admit to not caring a whole lot unless the client is paying a premium for IE5.x support.

Conditional comments are an issue with me. I organize my stylesheets by context, which implies that hacks should be adjacent to the original selectors. The CCs separate hacks from the defaults, making debugging or maintenance more complex than it should be. IE7 is still a virtual unknown, so I don’t know just how I’ll be dealing with its shortcomings; conditional comments are not a preferred solution.

How about using the “margin:10px” in the div#news rather than “padding:10px”. That might solve the problem in situations where padding isnt really required (like when there is no background to be thought of, etc.)

That was good explanation of IE’s box model,
Well as long as we have browsers that just won’t observe the discipline, we’ll have to use either of your tricks.
I personally would still prefer the extra markup. As that is not something extra ordinary like the “w\idth” thing, and still solves the purpose.

I’m able to handle the width/height issues with the !important syntax.

A hack is still a hack. If someone says “hack,” inelegant is not far behind. To quote the article you link to:

Assuming IE6 will not fix the correct implementation for the !important declaration and assuming that if IE7 does, they’ll also implement min-height correctly since at the pace they’re going they’re fixing CSS like mad crazy cows. Is that too many assumptions? But wouldn’t you agree?

Yes, I think it assumes too much. No, I wouldn’t agree. I respect Dustin a lot. But using CSS hacks, even if they are never fixed, when conditional comments are readily available seems like misplaced effort. Granted it was 2005 and CSS hacks (and “discovering” them) were all the rage when the article was written. Now, though, conditional comments make CSS hacks obsolete.

Conditional comments are A Hack Apart, though. Ideally, something like #1 could be used to better ends. But if you need IE to read something different than other browsers, conditional comments are the way to go because they are either supported or ignored, rather than misinterpreted.

My preferred method is to avoid situations that cause problems, andkeep IE6 in quirks mode whenever possible. I’ve never found IE6’ ‘standard mode’ to be very ‘standard’, and the box model problem is not a real problem, IMO.

So, by triggering ‘standard mode’ in ‘standard compliant browsers’ (including IE7 in most cases), and handling IE6 and older IE/win versions as ‘quirks mode’ browsers, the old ‘* html’ hack is available for fine-tuning of the ‘IE box model’ or whatever else older IE/win may need.

@Tanny O’Haley

In ‘quirks mode’ Opera will fall back to the old ‘IE box model’. Firefox, and probably the other browsers you mention too, will fall back to the old ‘NN4 box model’, which I haven’t studied but I think it is closer to the ‘W3C box model’.
Anyway, by following #1: ‘avoiding situations that cause problems’, there aren’t all that many differences to worry about.

Also: leaving out optional end-tags for list-items and paragraphs is perfectly valid HTML, and should not cause any problems. That means that you may add a ‘standard-triggering HTML doctype’ just for the sake of triggering browsers, and get a near perfect result across browser-land. Browsers use full ‘error-recovery’ for HTML anyway, regardless of mode.

I’m confused as to why this is being posted now. Using a proper doctype, IE6.0 and newer uses the correct w3c box model. No need for hacks or workarounds—just use a doctype to put the browser into “standards” mode.

Margins are handled a bit more complex than your example shows. You’re
into collapsing
margins,
which means you can get the result you want - not just the one you
describe.

@Brian Crescimanno:

I think that’s why Roger wrote:

If you already know how the different box models work and how to
handle Internet Explorer, there is nothing new for you here. If you get
different box dimensions in IE and other browsers without knowing why,
keep reading.

Sure, we know the ‘different box models’ and ‘standard compliant mode’
and all that stuff more or less ‘inside-out’, but there are plenty
around who do not - or simply can’t control ‘browser modes’. Some things
are worth repeating.

bart - I’m doing it by content negotiation on server but it’s not solution when you want to have static files.
The only other way I know would be the use of @media {} and IE conditionals but I’m not sure is it great solution (especially @media {} part)

Nice article!
I just don’t get why everyone is so upset with the IE box model?! Ignoring the fact that only the IE supports it, in my opinion it’s a lot better than the W3C box model.

If you are working with percentages you should know what I mean. Just add one border in px and your whole concept is no longer working using the W3C model. In my opinion it is a lot easier working with the IE box model.

Well I probably haven’t got the expert knowledge to see the W3C box models advantages…

Sorry to carry on with this, but are you saying about their diagram - yes this is how IE renders from IE6 onwards, or yes they show the IE5 bug correctly?

If the latter then why is their diagram showing IE5 to be wider than the W3C spec?

As you explain here (as they do), IE5 constrains to the content width adding padding and borders within, while standards compliant browsers add on the padding and borders thus making the element wider. So as I see it the W3C and IE widths on their diagram are the wrong way round.

Just wanted to add — I encountered my first case of IE doubling margins on floated elements and was able to fix it utilizing the Tan hack (http://tinyurl.com/9yld6). I just re-specified the margin value in the css hack that was in the original rule and it killed the doubling and preserved my floats.