Internet Explorer and the Box Model | August 4, 2005
Everybody knows that Internet Explorer gets the CSS box model wrong. According to the specs, the width property relates to the width of the content area. Padding, borders and margins are added to this, in order to calculate the total size of the box. Internet Explorer incorrectly sees width as the sum of the content width, padding and borders, adding only margins to calculate the size of the box. This means that if you specify a dimension and then add padding, the box will be smaller in IE than every other browser.
Many people have berated IE for this flaw, however I actually think Microsoft got this one right. I personally think the W3C box model is flawed and feel that Microsoft’s original approach makes much more sense. Here is the reason why.
Quite often I’ll have a floated element, inside another floated element. I’ll want the child element to take up the full available width, so I set it to be 100% wide. Now I want to create a fixed width gutter on the inside of the element to let the contents breath. To do this you’d naturally think about giving the element padding. However wait a minute, the total width of your box is now larger than the width of the parent and your layout is shot to hell.
There are ways around this. For instance you could apply your padding to the elements children, either explicitly or using the child selector. Alternatively you can add in an extra element. However both these methods are messy and a bit of a hack. If the parent element has a known width, what I usually end up doing is setting the width of the child explicitly to account for my desired padding. However this seems really unnecessary and always makes me feel slightly uncomfortable.
This issue is probably the main reason why I shy away from flexible layouts. Sometimes you just don’t want to set your padding as a percentage, the available options are all less than satisfactory. It would make so much more sense if padding was applied on the “inside” rather than the “outside”, the way IE5 does.
Failing that, I’ve often wished I could include simple sums in my width declarations. Maybe something like this.
#wrapper {
width: 100% - 24px;
padding: 0 12px;
}
Now something like that could come in very handy.
Comment
While I’m on a rant, my top CSS3 request would be an ancestor and a parent selector. How useful would that be!
Comment
I’ve long wished I could use math in my stylesheets… imagine what could be done if my style sheet could do simple calculations [specifically handling: *, /, -, +, >, <, >=, <=, (), and | | ]
- drools *
I wonder if it couldn’t be possible to run the css through a parser of some sort to handle the calculations? Could javascript or PHP do that? Man… that would be amazing.
Screw W3C! Anyone out there have the chops to work up a CSS calculations engine?
I’m guessing we’d have to have syntax in the CSS… perhaps quare brackets to delineate equations? It would also have to handle multiple units (%, em, en, ex, px, pt)…
- more drool *
Comment
And I second the ANCESTOR and PARENT selectors… I could use those every day but Wednesdays.
Comment
I agree that the IE method is more logical, but if we started doing things because the made more sense to us then standards would be pointless ;)
It’s at times like this that you realise that the W3C got the rest of it spot on ;)
Good post though, nice to see people sticking up for the big guy when they have reason to :)
Comment
There’s a note in the Values and Units module of the CSS 3 draft proposing that a calc function be added to CSS to allow something like width: calc(100% - 24px); to work as expected. Looks like it could be quite useful :-)
Comment
I agree, Andy. When I go to pack a box, I put the padding inside of it, not out. On this one, MS clearly had a logical thing going on.
And I also agree, ancestor and parent selectors would, in the parlance of our times, rawk!
Comment
I agree again that IE has the sense. Once I set my widths and realize I want more padding, I shouldn’t have to reset my width to fit that new padding while still retaining the comprehensive width of the box (content+padding+border). Still, I would like standarized box model. I’d rather have everyone agree on something, even if its not the best than have some making more sense than others.
Comment
I’m with you too, Andy. Whenever I’m playing around with the DOM for awhile and then switch to CSS I start having those thoughts of “why can’t I access the parent node here?”
What gets me with the IE box model is when I go and anticipate the problem and include some hack code to remedy it from the get-go.. then when I test the silly thing I find that the hack is actually wrecking it, and if I just remove it then IE treats the box like the other browsers… I think IE just does the opposite of what I think it’ll do.
But yeah I have to admit it’d make sense if the values in “height” and “width” were trustworthy indicators of the final box size.
Oh, and how much I’d love being able to calculate in CSS! That would definitely save a ton of unnecessary elements and lines of CSS. Go Units and Values module!
Comment
I agree that Microsoft’s implementation of width is much more logical. I’ve definitely been frustrated when using floats and trying to calculate widths accurately.
Comment
Agreed. It’s a bitch to calculate width when all you want to do is give it a little breathing room. Good analogy, Molly.
Comment
Spot on.
I’ve also banged my head in the wall, and naïvely googled width: 100% -24px and the likes, hoping someone had figured out a way to do it. Of course I knew the search would be in vain.
But oh, how many projects would’ve been nicer in structure and design, had it been available.
Comment
Andy, now come on stop this. This must be the forth or fifth post where it would seem your reading my mind:
- K750i/K700i (ditto on the want one/have the other)
- Canon Ixus 50 (yes please, my Ixus 400 now seems embarrisngly brick shaped)
- The perfect web team (my company to a ‘t’)
- Apple Market share (fighting xp on a daily basis at work)
- … …
Seriously this has got to stop because it’s getting kind of freaky;-)
Then again perhaps I’ll just redirect my site to yours as I never actually get round to blogging about these things - my bad.
Needless to say - I feel your pain on the liquid box model problem. How my heart sank when I thought I’d give the 100% - 24px formula a try…. in fact I probably used those figures - damn you!!!!!
Comment
Wow. I’ve always been thinking like that. It’s way more logical that padding and border declarations are included in the width declaration. You need less elements that way. But oh well, we’ll have to live with that drawback just as we have to work around IE’s defieaces evers day… :)
Comment
I think everyone secretly prefers the IE5 box model, we were just waiting for someone else to admit it first.
Comment
Mmm, but once you start doing maths within CSS, then they sort of become Cascading Scripting Sheets, rather than Style Sheets: You can achieve this at present with JavaScript and the (W3C endorsed) Document Object Model, designed for things like that.
Whether other aspects of the CSS specification are shortsighted or nonsensical I’m not going to argue about, but actually using CSS to do maths seems a little… away from its core purpose (even if that helps it achieve its purpose), at least to me.
Comment
I agree. When I first started using CSS for designing pages, I was a little confused and thought IE had it right. It just made sense to me that way. Then after I read the box model diagrams, I realized I was doing it wrong but it still didn’t make sense to me.
And have you ever tried to explain the box model to others who are learning CSS? Everytime I explain, they look at me and are confused because they would imagine it differently, or in other words, the way I first thought it was or the way you just described it.
Thanks for the backup though; it’s good to know I’m not the only one…
Comment
I remember bringing this up on irc in #css or #html over a year ago and being blasted by everyone in the channel! (uhhggg… can’t stand the blind followers)
The only reason I can see for having padding on the outside is due to the image element. You couldn’t have padding inside an image. I guess they wanted to keep things consistent.
CSS3 might have a solution for this with the “box-sizing” property. PPK talked about it a while back:
http://www.quirksmode.org/css/box.html
Comment
While we are on requests - does anyone else get really irritated at not having variables in CSS. I want to be able to define things like:
#Content StandardPadding {20px 45px}
or CornFlowerBlue {#7799ff}
And see it refered to throughout the css. Variables arguably make CSS simpler to understand too, and add the power to change a large amount of different rules at once and consistently. Maybe I should start processing my CSS with PHP, but its not really as slick.
Andy.
Comment
Simple maths in CSS would be pretty fantastic - percentages minus pixels would probably be the one I’d use most. Hope this does come through in CSS3.
Comment
If you’re talking about doing something like this only in internet explorer (since its broken box model is rather confusing) then there is always expression();
I found it quite useful when building an elastic layout recently.
Comment
AMEN! The W3C failed to realize that the outside width is a lot more important than the inside. But until 20 years from now when innerwidth and outerwidth properties are added to CSS 8.0, I cheat a little: I use the IE box model, and use “-moz-box-sizing:border-box;” in my stylesheets to force Gecko to do the same.
Comment
Parent selectors, useful as they may be, kind of go against the Cascade aspect of CSS, though.
Also, someone mentioned it already but it’s a pretty important thing: the CSS3 box-sizing property.
I may be wrong on this, but if you trigger IE6 to be in Quirks mode, it’ll use the MS box model (rather than the W3C one), and if you then have all modern browsers use that same box model through the box-sizing property, then all browsers will behave the way You want them to, Andy.
I’m totally not sure whether all modern browsers already support box-sizing though. Mozilla has had it as -moz-box-sizing for over a year, the -moz-prefix might’ve been dropped by now.
Comment
I don’t see how a parent selector would go against the cascade. You’d just need to give it the appropriate specificity. However it could make inheritance confusing.
Comment
@Silus Grok:
It’s pretty simple to setup your server to parse CSS files as PHP, so then you can add PHP-style calculations to your stylesheets (and also set up global CSS variables like colours and widths at the top of the document, so you don’t have to keep changing several declarations when the branding requirements change).
Google for “Apache AddType directive” for more information.
Comment
I’ve been hankering after simple sums in CSS for a while. It would make life so much easier. As would being able to refer to family eliments and named elements.
.float {
width: #main_container - parentElement;
}
Comment
There are times when both box models make sense. I vote for another tweak to the border, padding and margin attributes: inside and outside:
border: 2px solid #CCC outside;
margin: 4px 2px 4px 2px inside;
padding: .5em inside;
outside would add to the width of the element, inside would take away.
I suspect the borders might get a bit funky if you you mixed inside/outside around the same box…
Comment
Internet Explorer doesn’t get it wrong if you do it right, that is, if you use the HTML 4.1 Strict doctype (or xhtml). (I think, I always copy-paste from somewhere.) If you skip the doctype or go with transtitional it’ll behave as previous versions that did get it wrong.
What’s more annoying is that Gecko makes very small objects bigger than they’re supposed to be in some cases unless you set font-size to something like 1px.
Comment
I think math is too complex for CSS. As Faruk says, box-sizing would solve most of the problems here. Although I’m not quite sure where discussions are at, from reading what I believe to be the latest version of that bit of the spec (http://www.w3.org/TR/2002/WD-css3-box-20021024/).
I’d like something like:
width-edge: content;
width-edge: padding;
width-edge: border;
width-edge: margin;
Maybe that’s a bit too much, but it would be pretty flexible. And for elements and child floats, I’d love something like this:
child-floats: contain;
child-floats: normal;
Comment
Not only do I agree but I want to thank you (and Molly for the analogy). I’ve always kinda thought I understood the box model, or at least I understood the impact of it. But it’s only now that I “get” it, it’s clicked, the light bulb is on!
I guess this is another instance of ensuring input of ALL user types to a specification. The MS approach seems the most “real world” whilst the standard seems too smart for it’s own good in this area.
Comment
I disagree entirely, and think the Box model is perfect for what it does.
Taking the example of adding packing to a box - you buy a box for the size of the item it contains, not for the item and an estimation of packaging and wrapping paper.
Similary, in CSS, you are specifying boxes to contain something, (normally a predetermined amound of content/images), so giving it the width of the item it contains is simpler and easier, because once that fits, you can modify other properties.
This probably comes down to the way people develop CSS, (and how you approach a problem - from the inside out or outside in), but for what its worth, it always seems to make sense when I make things.
(Not saying the whole width:100% thing is not annoying, it is. Would like to see 100% - 20em r something).
Comment
It’s always painful to say MS got it right - but they do on this one. The spec is counterintuitive for exactly the reasons Andy sets out in this post.
My other gripe with the spec is it tends to result in more ‘magic numbers’ in your CSS. I want a box that’s 600px wide -
code comprehension gets increased tenfold by writing “600px”, than writing “580 + 10 + 10 px”.
And calculations in CSS would also be ver. ver. cool.
Comment
Parent selectors are a tricky subject. The most important thing to consider here is that with parent selectors, you’ll end up with a lot more problems with rendering. Most of these will be down to infinite loops, where the value of a property depends on both the parent and child of the element concerned. It would make design a nightmare and cause chaos for many.
Comment
Well, there was, is, and will be much discussion about the box model, and one could definitely argue that “Microsoft got this one right”. But, it’s not that important how it’s actually specified, it’s important that it’s actually implemented the same way everywhere. And that’s the mess with IE…
Comment
I think that everyone who uses CSS seriously believes the MS box model to be the right one. Despite my zen garden jab. ;)
If Safari supported the CSS3 box-sizing suggestion I’d dump the W3C model altogether!
Comment
Funny. I have always thought this, but really was afraid to say anything for fear of being a standards heretic.
Thanks for the post. I’m glad I’m not alone on this one.
Comment
You took the words right out my mouth with sums. Theres been many times i knew my design would work with a sum added to it.
Comment
I hear you on the arithmatic front Andy. How many times have a wished only for some simple addition and subtraction. I’d be happy with just that, but take it one step further and add some really basic algebra to the equation and you could do some great things. Imagine not having to specify a width at all in fixed terms and just being able to set a div to X width so it matches all of your other divs set to that width. Equal stretchiness… it would be wonderful.
Comment
I think we’ve all been so busy promoting standards they we’ve become a little scared about criticising them.
I think other developers would see web standards in a better light if it wasn’t for the strict stance taken by some proponents.
Better to be honest about the imperfections than say everything is rosy and have people pull their hair out when it ends up not being. Just as I do with my clients, web standards advocates need to manage people expectations a little better.
The reason for my post is that I see a lot of IE bashing going on at the moment. A lot of the time it’s fair, but sometimes it’s worth redressing the balance slightly. Sure IE 5 got the box model wrong, but I can see why they did it the way they did.
Comment
I completely agree with this. I was actually terribly confused for quite a while when I was starting out with CSS. The question for me with regards to the W3C convention is: What’s the difference between Margins and Padding then?
Comment
This conversion (the bit about CSS variables anyway) got the old gears turning and I came up with a server-side implementation that doesn’t involve inline PHP. If that interests you check out CSS server-side variables or CSS-SSV for short (long?).
Comment
Whoops - My remark concerning “What’s the difference between Margins and Padding” came in a flash of silly realization - evidently the border goes between the two…
Comment
I see how Internet Explorer’s approach seems more intuitive. And it could make some layout tasks easier if it was the standard.
I guess the W3C did it their particular way to be consistent with table metrics and the layout methods people had got used to, i.e. borders and cellpadding added outside a table cell’s specified width – even in IE6. AFAIK, print designers would also be more familiar with the W3C model.
Microsoft really hasn’t done anyone a favour by doing it their own way, regardless of it being better or not. It undermines both the W3C and standards compliance while creating an everyday need for messy workarounds.
:(
Comment
Couldn’t agree more - much more sensible to stake out the footprint of the element explicitly. And, yes, I’ve often wanted to mix calculation units especially when dealing with fluid designs.
Comment
You’re right Andy: an ascendent selector would be an indispensible addition to CSS3. This must get implemented!
Comment
Hows about namespaces:
.float {
width: #main_container.width - parentElement.width;
}
Comment
I haven’t read all comments yet, but…
1. The IE box-model is not more logical than W3C box model. Imagine you want to add a dropshadow effect to an image:
img { display:block; padding: 0 10px 10px 0; background:url(dopshadowimg.jpg) bottom right no-repeat; }
Thanks to W3C box-model you will see the background for image element in the padding area of image element. In old IE box-model padding is underneath the image, so even if the backround is rendered you won’t see it.
2. If you really need other browsers to emulate IE box-model you can use
{ box-sizing: border-box; -moz-box-sizing: border-box; }
I know it works in Gecko and Opera, but I don’t know if it works in KHTML-based browsers… Ofcourse you need to switch IE into quirks mode to use the non-standard box-model in IE6.0+
Comment
Great. I’ve been ranting about this for years, but hopefully now that a “standards advocate” has come out of the closet, and even the esteemed Mr. Hicks (now that Mr. Oxton has shut down shop, you definitely have the best looking site on the web, sir) agrees.
What next? Will Mr. Zeldman admit that not providing a means for an element to be vertically centered inside its container was, perhaps, a slight oversight on the part of the W3C? Even though there is a “vertical-align” property, which applies to something more obscure and less useful in everyday coding?
Will Mr. Meyer concede that, perhaps, just perhaps, being able to set a box element to grow to fill its container might come in handy to Joe Web Developer? (Use Case: A Wrapper DIV contains three floated DIVs. A property is set which causes each interior DIV to grow to the height of the container DIV, which if not specified explicitly, is the height of the longest interior DIV. And no, “display:table-cell” is not sufficient, as table-cells can’t have margins, only padding.)
Will Mr. Shea declare outright that the float model is arcane, useful only in edge cases, and the lack of support for the standards recommended “display: inline-block” in “standards compliant” browsers is a scandal worthy of the front page of the New York Times?
Another useful, but non-standard thing IE provides is the “expression” property, which allows you to use the DOM to set CSS values, for example:
<div style=”height:expression(this.parentNode.offsetHeight”>
Of course there are accessability issues with this - does it work if CSS is on but Javascript is off? However, in a closed, targeted environment, it’s amazingly useful, as are behaviors, another non-standard innovation.
And let’s not forget the current darling of AJAX™, HTTPRequest, a non-standard implementation by “standards compliant” browsers of an IE innovation.
Also, the box model works as recommended by the W3C in Strict Mode.
<disclaimer>
CSS is great. I use it every day. It’s an amazing tool for seperating content from presentation. Unfortunately, it’s presentation tools are somewhat lacking.
</disclaimer>
Comment
I thought that Mr. Zeldman already said that he thought that Microsoft got the box model right in Designing With Web Standards.
I agree with you, the Microsoft box model seems much more logical to me.
Comment
“I don’t see how a parent selector would go against the cascade. You’d just need to give it the appropriate specificity. However it could make inheritance confusing.”
— Andy
Andy, the Cascade is logical and useful because it inherits only downwards. What would happen if you use a parent selector and specify a color:#000 to it? Would that cascade as well? If so, it would cascade in the other direction! Thus, all parents and their parents would inherit that color property.
In that sense, parent selectors can create numerous logistical nightmares and would probably just confuse the hell out of people.
My two cents, anyway. :-)
Comment
Well, frankly, I don’t care which one is correct, I’m just a CSS padawan, seeking a consistent way of handling these issues.
While Zeldman and Meyer and such blather on about high-minded affairs, I’m trying to get my site of the day done, and getting frustrated that I can’t have a variable height of a floated object (Why, oh why can’t we create a floated left nav that will stretch dow to the bottom of the content, so and item can be placed on the bottom?), and am terribly worried that when MS rolls out the new IE in Vista, or before, that all our beloved box-model hacks will break, and we’ll be stuck as we won’t be able to sort between the versions of IE without massive browser detection JS.
I really, really like the suggestion up a ways of having the inside and outside being able to be applied to padding. That might make margins irrelevant, but it would clear things up.
Comment
I have two comments.
If we are going to discuss calculations css numerical values, it would be benficial to allow reference to other numerical properties of the element.
For instance, lets imagine that I have the following:
<div class=”notice foo”>Hi there!</div>
<div class=”notice bar”>Hello World!</div>
And lets assume that for some very good reason you have the following CSS:
.foo {padding:20px;}
.bar {padding:10%;}
Now if we know we want notices to be a specific width, it would be nice if we could say:
.notice {
width:calc(200px - paddingLeft - paddingRight);
height:calc(400px - paddingTop - paddingBottom/2;
}
This seems to me to be a reasonable requirement, although you could easily get yourself into a complex circular calculation.
Second, I want parent selector so I can do the following (assuming ^ denotes a parent):
input[disabled] ^ .field {color:#555;}
input[readonly] ^ .field {color:#0F0;}
This is a matter only of presentation and right now, I would have to put readonly or disabled as classes on my outer div. Inefficient.
Not only that, I’ve often had it where I might have a fieldset where the legend contains two radio buttons, one enables the fieldset and the other disables it. To do this you have to write javacript to modify the class of the containing fieldset, or some such method (I can think of a number of approaches). This javascript must be purely presentational, and as such belongs as CSS (something you could easily do with a parent selector). Its purely presentational because the proper way to handle these situations is to assume all your fields are comming back and write your server code to handle it. Relying only on javascript to keep your data valid is a good way to get bit by script kiddies who send malicious HTTP requests without using your page.
And Faruk Ateş has confused cascade with inheritance. So Faruk, in your example, the parent element would have its color set to black. All of its children would simply inherit that value. The cascade only applies to how you decide which property applies and for that you only need the specificity rules. As far as I know, nothing new is needed. Since child, sibling, descendant, etc. have no real impact on specificity, I don’t see why the parent should.
I seems to me though that having a parent selector might cause some confusion, assuming Faruk is a typical example.
I think it would be better then to introduce predicate notation, like we have in XPath. This should be more clear. We’re running out of brackets so I’m going to use simpe ( ) to indicate predicate instead of [ ] as we would have in XPath.
With predicates, my earlier example becomes:
.field(> input[disabled]) {color:#555;}
.field(> input[readonly]) {color:#0F0;}
which can be read as “an element with a classname of ‘field’ containing a input child who has a disabled attribute set”. No confusion about which directions things go (only we need to find some more brackets to use).
Comment
Totally agree. When it’s time to do the box model dance at code time, I have to literally take a deep breath before diving in. IE5’s version seems a better and more logical.
Comment
Just a hint, that might help some people: You can use JS expressions in Stylesheets like this:
width:expression(document.body.clientWidth-18);
or even emulate a mxa-width property like this:
width:expression(document.body.clientWidth > (850) ? “850”: “auto” );
helped me quite a few times
Comment
I believe I read somewhere (in Eric Meyer’s Cascading Style Sheets - The Definitive Guide, maybe?) that future implementations of CSS will allow the author to choose how the box model works; the current “correct” way, or the IE5 botched way.
And no, the current implementation doesn’t make sense at all no matter what anyone tells you, never never ever.
Comment
One way of getting round this is adding negative margins to your internal elements. You also need to double up on your padding. But try:
width:100%;
margin:0 -24px;
padding:24px 48px;
with an overflow:hidden on the containing area.
I know it’s not very good maths though.
Comment
Did someone say 50% + 50px? http://www.cssplay.co.uk/boxes/plus.html
Comment
Negative margins to our rescue? For IE.
Comment
No offense, but it does not matter if it is (or seems) more logical.
The point is that Microsoft behaves in the Microsoft-typical way. They do just what they want and expect the world to live with it because THEY do it that way.
See it as you like, it is wrong.
Comment
I’d love ancestor and parent selectors! :-)
Comment
If you just do web apps for a company Intranet that has standardized on MS and IE6, then you can do this in your CSS:
width: expression(document.body.offsetWidth - 145);
Yeah, I know… MS got a lot of things wrong, but sometimes they get it right.
Comment
Working around one poor decision in the box model is so amazingly trivial; this is why nobody discusses it. What I resent is the time I spend becoming an “IE workaround expert”. Put that in your job description.



Comments on: Internet Explorer and the Box Model
Jump to the comment form