Webbrowser height calculation top margin falsely taken into account?
In one of our projects we noticed the following strange calculation in all major browsers (Firefox 22.0, Chrome 28.0.1500.72 m, IE 10.0.9200.16521)
Take into consideration the following HTML code:
<div> <div style="height:100px">Head</div> <div style="height:200px"> <p style="margin:10px">This goes wrong</p> Wrong wrong wrong </div> </div> <div> <div style="height:100px">Head</div> <div style="height:200px"> Right right right <p style="margin:10px">This goes right</p> Right right right </div> </div>
You can find the code example also on: http://jsfiddle.net/Cnjdg/
If you inspect the calculated height of the 2 toplevel DIVs you'll notice something strange: DIV1 is 310px high while DIV2 is 300px high... Now logic tells me that a DIV is as high as its children (especially since no special styling has been applied) what would mean that for me both DIV elements should return 300px height.
So when there is an element with a top margin at the very top of a child it seems that this height is being taken into account when calculating the height of the parent. Is this a bug? Is this intended? To what purpose?
In fact, the p with content "This goes wrong" is actually pushing its parent down, so the inspector is telling the truth. I modified your fiddle adding color and a higher margin. Now it's obvious that the height of the block is different and the pushing behaviour is clear. http://jsfiddle.net/Cnjdg/1/
<div> <div style="height:100px; background-color: blue">Head</div> <div style="height:200px; background-color: red"> <p style="margin:50px">This goes wrong</p> Wrong wrong wrong </div> </div> <div> <div style="height:100px; background-color: green">Head</div> <div style="height:200px; background-color: yellow"> Right right right <p style="margin:50px">This goes right</p> Right right right </div> </div>
This is intended, not a bug. And as far as I know there isn't an special purpose on that. If you don't like this behaviour you could use padding instead.
Furthermore, margin also collapse each other. If the parent has a margin of "70px", then the whole margin would be 70px not (70 + 50)px. And if the "Head" div has a 30px bottom margin. The whole margin would be 50px, not (30 + 50)px.
If you have to use margins, you can use a trick playing with pseudoelements: http://jsfiddle.net/Cnjdg/2/ In a pseudoelement in the parent...
content: "\00a0"; display: block; height: 0; overflow: hidden;
Finally having a bit of time and inspired by the reply of davidgnin I sought deeper and did a dive into the W3C boxmodel definitions. This definitely answers my question on terms of Is this a bug? and Is this intended? and the answers are: NO and YES
You'll find the reason explained here, where it clearly states the following:
The top margin of an in-flow block element collapses with its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance.
The reason as to why this is done is a bit unclear to me (so I welcome anyone who can explain the reasoning behind this) thus I am unable to answer my question of To what purpose?
Luckily knowing why this occurs also enables us to counter the effect:
- Establish a new block formatting context by for example using overflow:hidden
- Separating the parent and child by a padding, border, inline element or clearance
I hope that this may help someone ending up in the same situation.