2

I've encountered this problem before and have not really found a solution. I have this html (simplified):

<div class="outer">
    <header>my header section</header>
    <div id="body">
        <h1>Page H1</h1>
        <p class="content"></p>
    </div>
    <footer>footer section</footer>
</div>

And I'm trying to get the actual height of #body (using jQuery) like this:

var b = $('#body').outerHeight(true);

But that is not returning what I think is the correct height. The height I expect is the height that FireFox also reports in the "Box Model" (in Developer Tools). But jQuery is returning a different value, which appears to exclude the top margin of the h1 tag.

I also tried to use innerHeight of #body but it returns the same value. Anyone has an idea of how to do it, hopefully without having to iterate through the child elements?

I have this fiddle for your reference.

Frank Fajardo
  • 7,034
  • 1
  • 29
  • 47
  • the problem is that there is a margin between #body and header [http://jsfiddle.net/e4g78/2/](http://jsfiddle.net/e4g78/2/) – Abraham Uribe Nov 05 '13 at 23:26
  • I don't have enough time to investigate this properly as an answer, but it might be also worth having a look at `getBoundingClientRect().height`? http://coding.smashingmagazine.com/2013/10/06/inside-the-box-with-vanilla-javascript/ – StackExchange What The Heck Nov 05 '13 at 23:30
  • if you want the parent's bounding box to include a child's margin, read this: http://stackoverflow.com/questions/1762539/margin-on-child-element-moves-parent-element – lbstr Nov 05 '13 at 23:32
  • When are you trying that? just as it is? on `$(function)` ? on `$(document).ready()` or in `$(window).load()` ? – Toni Michel Caubet Nov 05 '13 at 23:42
  • @AbrahamUribe, I do not want to (nor think I should) remove the margin on h1 to solve the problem. – Frank Fajardo Nov 06 '13 at 00:01
  • @ToniMichelCaubet, the fiddle answers your question. (I do it when the document is ready.) – Frank Fajardo Nov 06 '13 at 00:02
  • You can float your elements, give them display inline block, or try other solutions to remedy the collapsed margins described in my answer. – Stuart Kershaw Nov 06 '13 at 00:21

2 Answers2

4

This may be due to a box model feature known as 'collapsing margins'. Individually, these elements should return their proper calculated heights, but when margins collapse as stacked, the result may account for your discrepancy.

Here's an excellent article describing the scenario: http://reference.sitepoint.com/css/collapsingmargins

In simple terms, this definition indicates that when the vertical margins of two elements are touching, only the margin of the element with the largest margin value will be honored, while the margin of the element with the smaller margin value will be collapsed to zero.

This behavior is best demonstrated with a short example. Consider the following code:

h1 {
  margin: 0;
  background: #cff;
}
div {
  margin: 40px 0 25px 0;
  background: #cfc;
}
p {
  margin: 20px 0 0 0;
  background: #cf9;
}

<h1>Heading Content</h1>
<div>
  <p>Paragraph content</p>
</div>

enter image description here

Further info can be found at the W3C Box Model spec: http://www.w3.org/TR/CSS21/box.html#collapsing-margins

When two or more margins collapse, the resulting margin width is the maximum of the collapsing margins' widths. 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 maximum of the absolute values of the adjoining margins is deducted from zero.

Stuart Kershaw
  • 16,831
  • 6
  • 37
  • 48
  • Thanks @Stuart. I get what you and the article are saying, but it does not quite explain why jQuery would calculate the height of the container without considering the margin (collapsed or not) of the child elements. – Frank Fajardo Nov 06 '13 at 00:21
  • The margins are not factored into the document height when calculated as a whole, because they are then collapsed. If you remedy the collapsed margins does that solve the discrepancy? I'm very curious. Try floating the elements to test. – Stuart Kershaw Nov 06 '13 at 00:23
  • I think your answer explains the why. So thanks for that. And it lead me to find this hack: http://stackoverflow.com/questions/7909956/how-to-calculate-an-elements-height-considering-collapsed-margins. This appears to work based on this updated fiddle: http://jsfiddle.net/e4g78/3/ – Frank Fajardo Nov 06 '13 at 00:51
  • Thanks @frank, I think the same could be achieved by simply applying a transparent border to the element in your CSS, or by using floats, or taking any of the routes described in the linked W3C spec on canceling collapsed margins. Interesting question here though, and I learned some stuff in the process. – Stuart Kershaw Nov 06 '13 at 01:29
0

@Stuart's answer explains the height 'anomaly', if I can call it that. Thanks to @Stuart. His answer led me to look for a solution for that scenario.

Here's an SO item which mentions a hack, which appears to work on IE8, Chrome and FF. And it addresses my need. Here's my updated fiddle for anyone interested. Basically, I had to change the way I calculate the height as follows (and remove the wrapping afterwards):

   var b = $('div#body').wrap('<div style="border:1px solid transparent;"></div>' ).parent().height();
   $('div#body').unwrap();
Community
  • 1
  • 1
Frank Fajardo
  • 7,034
  • 1
  • 29
  • 47
  • Thanks @frank, I think the same could be achieved by simply applying a transparent border to the element in your CSS, or by using floats, or taking any of the routes described in the linked W3C spec on canceling collapsed margins. Interesting question here though, and I learned some stuff in the process. – Stuart Kershaw Nov 06 '13 at 01:27
  • Unless you *actually want the collapsed margins! In which case your solution solves the problem, gets the proper height, and then reapplies the collapsing :) – Stuart Kershaw Nov 06 '13 at 01:35
  • Really interesting scenario. – Stuart Kershaw Nov 06 '13 at 01:35
  • Hi @Stuart, I really cannot change the content nor the content's styling so I'm hesitant to change margins or introduce floats. The hack is less intrusive. Yes, it is really interesting and without you telling me about collapsed margin, I would be pulling my hair by now :))) – Frank Fajardo Nov 06 '13 at 05:19