Could someone explain the Box Model Hack?
August 29, 2005 1:59 PM   Subscribe

Can someone properly explain to me the CSS Box Model (Hack)? Example inside.

After reading three books and a few web sites, I still can't get a page to render the satisfactorily in IE and the standards-compliant browsers.

Suppose I want a box element to be 500 pixels wide TOTAL (including margins, padding, border, content). Also:

-- I want the border to be 5 pixels on each side.
-- I want there to be 10 pixels of padding between the content and the border.
-- I want there to be 10 pixels of space (margin) between the border and any element next to it.

In a standards-compliant browser, I would write (I think):

.post {
width: 450px;
margin: 10px;
padding: 10px;
border-width: 5px;
border-color: #000;
border-style: solid;
}

At least, that's how I understand it (though one book says that margins are included in overall width and another doesn't mention margins at all).

So, assuming the above code is correct, how would I write the code so that it also renders satisfactorily in IE? I realize (or at least I think) that the resulting box in IE would have less room inside for content but that doesn't matter to me as much as the overall width and that the element beside it is the same number of pixels away in all browsers.

Please and thank you.
posted by You Should See the Other Guy to Computers & Internet (19 answers total) 1 user marked this as a favorite
 
I believe it would be as follows:

.post {
width: 400px;
margin: 10px;
padding: 10px;
border-width: 5px;
border-color: #000;
border-style: solid;

/* Corrected for IE6/Moz */
voice-family: "\"}\"";
voice-family:inherit;
width:450px;

}

This works because IE 5.5 stops parsing the rule at the voice-family hack, while IE 6, Mozilla and other standards-compliant browsers keep going.
posted by killdevil at 3:20 PM on August 29, 2005


This page and this page have good explanations, and here's a fancy-pants Flash demo.

The real problem is that the correct box model doesn't make any fucking sense. If I leave space around the inside of my sock drawer (i.e., add padding), the drawer doesn't magically get bigger, but it does in CSS.
posted by kirkaracha at 3:24 PM on August 29, 2005


Sorry, just read your comment above -- scratch my first response. If you want the box to be 500 pixels wide in total:

.post {
width: 500px;
margin: 10px;
padding: 10px;
border-width: 5px;
border-color: #000;
border-style: solid;

/* Corrected for IE6/Moz */
voice-family: "\"}\"";
voice-family:inherit;
width:450px;

}
posted by killdevil at 3:24 PM on August 29, 2005


Here is the original source of the hack, BTW.
posted by hyperizer at 3:29 PM on August 29, 2005


Here's a 3D diagram of the CSS Box Model and here's a good article that explains how it works and which browsers are broken. And here's a good visual comparison of the correct box model vs the broken IE box model.

In short, IE counts the margins and padding towards the total specified width of the element when it should not.
posted by geeky at 3:43 PM on August 29, 2005


Basically, in IE, the border and padding are inside the box (i.e. the total element width is width + margin*2 (one margin on each side)), and in compliant browsers, the border and padding are outside the box (i.e. the total element width is width + padding*2 + border*2 + margin*2). So, using this IE hack leaves you with:
.post {
    width: 450px; width: 480;
    width: 450px; margin: 10px;
    width: 450px; padding: 10px;
    width: 450px; border-width: 5px;
    width: 450px; border-color: #000;
    width: 450px; border-style: solid;
    width: 450px; voice-family: "\"}\"";
    width: 450px;voice-family:inherit;
    width: 450px;width: 450px;
}
html>body .post {
    width: 450px;width: 450px;
}
On preview: killdevil's got me a tad confused now (don't worry, it's easy ;) ). If you want the box to be 500px wide including the 10px margin, use mine; if you want the box to be 500px and then have an additional 10px margin around it, do killdevil's.
posted by boaz at 3:51 PM on August 29, 2005


Aarrggghhh. I accidentally put in a bunch of width:450's when I pasted in the non-breaking spaces. Let's try again:
.post {
    width: 480;
    margin: 10px;
    padding: 10px;
    border-width: 5px;
    border-color: #000;
    border-style: solid;
    voice-family: "\"}\"";
    voice-family:inherit;
    width: 450px;
}
html>body .post {
    width: 450px;
}
posted by boaz at 3:58 PM on August 29, 2005


Remember that hacks, such as Tantek's voice-family hack, may blow up in future browsers. I would suggest conditional comments to feed version-specific code to IE.
posted by Monk at 4:11 PM on August 29, 2005


Response by poster: Thanks for all the answers. I'll give this a shot and see what happens.
posted by You Should See the Other Guy at 4:13 PM on August 29, 2005


I'm a bit late to the party, but my preferred workaround is the * html hack, which would work thus:

.post { /* standards-compliant CSS */ }
* html .post { /* IE-hacked CSS */ }

posted by brownpau at 5:10 PM on August 29, 2005


And, for the record, IE is just as "Standards Compliant" as other browsers. It's just compliant to different aspects of the standards. I grow weary of "your browser sucks, my browsers r0x0r5!!11" arguments.

<sarcasm mode="layItOnThick">
I prefer the PSP browser, myself.
</sarcasm>
posted by Merdryn at 5:57 PM on August 29, 2005


If you're dynamically generating content (eg in PHP), you can detect the browser type and give them back references to different/additional CSS files. I use that to get around weird fontness in IE instead of making my text unreadably small in other browsers.
posted by polyglot at 6:10 PM on August 29, 2005


Merdryn: IE may be as "standards compliant", in your view, but it still suxx0rs, for many reasons. :)

Anyway, the correct box model used to confuse me as well, for the same reasons that confused kirkaracha above (the sock drawer model).

However, things become clearer when you realize that the spec allows you to add padding to images (which results in space between the image boundary and the border of the image). The sock drawer model doesn't hold up in this case, and it's my theory that the spec writers chose to apply the model for images to all box types, so as not to have different models for different types of boxes.

Again, it's just my theory, but it resolved my frustration with the model.
posted by o2b at 6:19 PM on August 29, 2005


Oh, and you could avoid most of the css hackery (not that I'm against hackery) if you put your div in a redundant parent div that controls the width. Set the redundant parent to your desired width (including space for the borders), apply the margins to the parent, borders and padding to the child, and specifiy no width for the child, letting it expand to fill the parent.
posted by o2b at 6:22 PM on August 29, 2005


The Box Model, as "standardized", makes about as much sense as boobs on a fish.

Yes, I said it.
posted by Merdryn at 6:26 PM on August 29, 2005


If you are pulling your hair out trying to get CSS to work, I have two general suggestions. One, make sure you are specifying a correct DOCTYPE that puts browsers into standards mode. Two, run your stylesheets through a validator to make sure you aren't making typos or thinkos that you are not aware of.
posted by Rhomboid at 8:28 PM on August 29, 2005


Response by poster: rhomboid, that's the problem. i run them thru the validator and it validates but the page doesn't look how I expect or want. :(
posted by You Should See the Other Guy at 8:30 PM on August 29, 2005


Just be glad no one is using netscape 4.x.

And, why not use javascript for browser selection?
posted by delmoi at 11:44 PM on August 29, 2005


IE6 uses the correct box model providing you're using a proper DOCTYPE, so you only need a box model hack to cope with IE5.x

I use a simplified hack which is less cumbersome and less likely to cause problems in future,e.g.
width:1000px;
w\idth:900px;
would give a width of 1000 pixels to IE5.x, but newer browsers will successfully parse the second value and give 900 pixels. You can put the backslash before any character that isn't a valid escape character, but generally you'll just need w\idth and he\ight

So for IE5.x include border and padding in your dimensions, for the other browsers don't include them (resulting in smaller values). That's all there is to it.
posted by malevolent at 3:00 AM on August 30, 2005


« Older Regular Expressions? PHP? Existing App?   |   Please share your general London tips. Newer »
This thread is closed to new comments.