Forum Moderators: not2easy
It has to do with collapsing margins and how the different browsers handle them, and which browser's handling of them is closest to the W3 specs.
The situation it springs from was trying to position a horizontal nav bar so that the top half overlaps the header <div> and the bottom half overlaps the content <div>. Here's the skeletal source code:
<div id="header">
</div>
<div id="box">
<div id="nav">
</div>
</div>
In the css:
#header{
width: 690px;
height: 150px;
margin-bottom: -22px; /*ie=-12px*/
background: #59171b url(images/dressertrim.jpg) no-repeat;
}
#nav {
width: 50.0em;
background: transparent;
}
#box {
float: left;
width: 700px;
margin-top: -1.5em;
padding-top: 2.0em;
border-top: 3px double #59171b;
}
The negative margin of -22px on #header pulls #nav up, putting the top border on #box even with the bottom of the background image in #header. Produces exactly the effect I wanted in FF.
IE, however, displays this with an additional negative 10px. In other words, the top border of #box overlaps the image in #header by 10px, instead of lining up with it's bottom. Somewhere in there, IE was adding an extra 10px, or -10px, I dunno.
The only solution I could think of was to hack IE the margin setting it seemed to want...
_margin-bottom: -12px;
...but I hate to use the underscore hack. I took a last ditch look at the specs for collapsing margins and saw this
In the case of negative margins, the maximum of the absolute values of the negative adjoining margins is deducted from the maximum of the positive adjoining margins. If there are no positive margins, the absolute maximum of the negative adjoining margins is deducted from zero.
This means that...
IE took the negative 22px, then subtracted the positive 10px on #nav to get the -12px that IE wanted.
Firefox, on the other hand, was fine with the -22px, and then also fine with the -12px result of the collapse.
Now I know better than to suggest that IE is following specs better than FF, but doesn't it appear to be the case here? IE subtracted the margins as per specs. FF apparently also did this, but before, when there was no positive 10px margin to subtract, FF was still displaying things as if that 10px value were there.
So the issue is, why did FireFox display things the way I wanted in the first place? Based on all this, it seems as if FF was not following specs (and , for the record, the FF Web Dev Extension assures me the page is in Standards Compliant Mode). It would also appear that, in this one instance at least, IE is spot on with the specs on collapsing margins.
Thoughts? Impressions? Knowledge to share about how different browsers handle margin collapses? I'd love to hear it all!
references
CSS2 recs for Collasping Margins [w3.org]
CSS2.1 recs for Collasping Margins [w3.org]
CSS2.1 is more specific than CSS2, and obviously not all 2.1 recs have been implemented?
your Example
Based on your explanation I would say IE is wrong because it seems to be collapsing the vertical margin of a floated box which in both recs is a no-no.
Putting a margin on the #nav should not collapse with anything. You also have a top margin on the #box div so it's that which should collapse if anything, but again it shouldn't because the top border should serve to stop the margins adjoining/collapsing. .. more on this below ..
I couldn't actually create the same thing as you describe just from the code you have provided so I'm gonna guess that there is a <p> element in there somewhere.. nav div?
IE definitely has a problem with handling top/bottom collapsing default margins especially inside floated elements. If you have a <p> element in there try specifically adding p {margin: 1em 0;} to the CSS and it should then appear to mimic FF.
If you then add a color to the #nav/#box divs you see the difference is that in IE it's margins are rendered with #navs background color, but if in FF they've got #box 's background. That is the real crossbrowser difference of collapsing margins. I don't think this really matters it's just a rendering choice.. the fact is that now both margins are correct. Try this code example, based on yours but negatives taken out of play for the minute..
<style type="text/css" media="screen">
#header{
width: 690px;
height: 150px;
margin-bottom: 0px; /* -22px */
background: #59171b;
color: #fff;
}#nav {
width: 650px;
background: #ffc;
color: #0f0;
}#box {
float: left;
position: relative;
width: 700px;
border-top: 3px double #59171b;
background: #fcf;
}p {margin: 1em 0;}
</style>
</head>
<body>
<div id="header">header</div>
<div id="box">
<div id="nav"><p>nav</p></div>
<p>box stuff</p>
</div>
now comment out the <p> margin rule and see IE crack up ;)
Also in your code that top border on the #box div should stop any margins adjoining (and therefore collapsing) with the the bottom margin of the header which again would mean that in your explantion IE is wrong again.. even if the float were allowed to collapse it's margin with the #box, the #box should not then be collapsing with the #header.
Methinks
As far as I've been able to determine all browsers handle collapsing margins more or less correctly, it's just the visual difference of the background rendering that causes "gaps" sometimes which throws people.
The biggest mistake IMO, yes is on IE's behalf, and it's handling of default margins (<p>, <hx>, <ul>, <form> etc..). I used to think and have said many times, that removing margins (from internal elements) and using padding to control spacing was the best answer, and perhaps it still is for visual/colored background/gap purposes, but the handling of the margins does appear to be correct as long as you actually override the defaults by specifying margins for internal elements in IE. Nowhere in the recs can I find a stipulation of which way the margins should actually collapse ie. upwards through the parent or downward to the child, and of course nothing about which sibling gets preference.. lol.. it says:
In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.
It just says "combines" it doesn't say which way, as in which element rules?
RE: your example if you take mine (override defaults internal margins and remove the margins/padding off the #box) you should just need that negative margin on the #header set to one value for all, it's not actually collapsing then it's just doing it's negative bit..
Is this making any sense ;) I doubt it.. most times I've tried to do examples there was always some other "quirk" came into play too..
What say you?
Suzy
First, I have to say that I feel like a fool, because you've gone through all that work and it turns out I posted the wrong html skeleton! In the actual page, the <div> order is
<div id="header">
</div>
<div id="nav">
</div>
<div id="box">
...
</div>
I realized the mistake in the post only on reading your response when you mentioned that floating box margins don't collapse. I thought, "Wait a minute, I knew that," and checked my code and sure enough, I posted it wrong. With the correct div order (above) the margins of #header and #nav, both unfloated, touch, with no borders between them, and so they collapse.
Of course, that still leaves the question of why, before #nav was given a top margin, the two browsers interpretted the negative margin differently.
Based on what you said about IE's handling of default margins, I suspect it has something to do with that, that somewhere in there IE was adding 10px by default, but I'll be d#!%$d if I can figure out where. There are no <p> tags, just an <h1> in the top of the header (whic has a fixed height much larger than an <h1> bottom margin) and a <ul> nav menu in #nav...could the <ul> margin have done it? Possible.
I feel bad that you went through that whole example and worked out a new solution, but I want you know that I've cut'n'pasted it into my design binder for future reference and use. :)
as long as you actually override the defaults by specifying margins for internal elements in IE
I feel bad that you went through that whole example and worked out a new solution, but I want you know that I've cut'n'pasted it into my design binder for future reference and use. happy!
<ul> nav menu in #nav...could the <ul> margin have done it? Possible.
as long as you actually override the defaults by specifying margins for internal elements in IE
I wonder if there is a shorthand way to do this, in other words, one CSS rule declaration that would set all margins on the page to 0? Since margins don't inherit, I imagine there isn't but it would be handy, yes?
Suzy
* {margin: 0;} - at the start of the stylesheet
If you're still giving this any thought, I experimentaed around with the above problem and found another thing that fixes it. Before I used a 10px top margin on #nav, which works by collapsing neg and pos margins to the value IE needed. I also tried adding that 10px top margin to the <ul> inside of #nav and it had the same effect.
I know the specs mention something cryptic about margins collapsing through the top of the parent. I never understood exactly what this meant, but I believe this is a case in point of that principle.
What I'm wondering now is what exactly IE's default top margin for <ul> is. Arfe IE default margin (and other property) settings listed anywhere or is it all hit and miss?
ANyway, thanks again for your response. I'm not sure why, but I think this collapsing margins stuff is just about the hardest thing in the specs to get my brain around.
sorry for the delay.. I only found this again recently and remembered someone had asked for it.
H4, P,
BLOCKQUOTE, UL,
FIELDSET, FORM,
OL, DL, DIR,
MENU
{ margin: 1.33em 0 }
Recommended default stylesheet [w3.org]: Note this is only recommended and as such it's not fully incorporated by all UA's. e.g. Opera doesn't seem to have incorporated bottom margins.. trying to suss out consistent collapsing margins therefore becomes failry impossible
I still think that overriding all the defaults and setting your own is the best way to set that consistency as well as the fact it seems to make IE behave ;)
Suzy