3

When the child of a div contains margins, those margins are not included in the calculation of div.offsetHeight. Except, however, when you do certain things to the parent div, including giving it 1px of padding.

The code below causes the reported height of the div to jump from 38px to 83px (the "right" size, including child margins). Adding a border to the element has the same effect.

What is going on here? Is this defined behavior? Also, is there anyway to get the actual height of the element (including child margins, but not its own margins) without this 1px hack?

(The context for this question is that I was resizing an iframe on window resize, and the calculations only worked properly when the 1px padding was included.)

var hasPadding = false;

var alertDivHeightButton = document.getElementById('2');
alertDivHeightButton.onclick = alertDivHeight;
var togglePaddingButton = document.getElementById('3');
togglePaddingButton.onclick = togglePadding;

function alertDivHeight () {
    var div = document.getElementById('1');
    alert("width of div: " + div.offsetHeight);
}

function togglePadding () {
    var div = document.getElementById('1');
    if (hasPadding) {
        div.style.padding = '0px';
        togglePaddingButton.value = "Add 1px padding";
    } else {
        div.style.padding = '1px';
        togglePaddingButton.value = "Remove 1px padding";
    }
    hasPadding = !hasPadding;
}
<div id="1">
    <h1>Hello, world</h1>
</div>

<input type="button" id="2" value="Alert div height">
<input type="button" id="3" value="Add 1px padding">

JSFiddle

Chris Middleton
  • 5,654
  • 5
  • 31
  • 68
  • 1
    *those margins are not included* because they ***[collapse](https://developer.mozilla.org/en-US/docs/Web/CSS/margin_collapsing)***. By giving a border/padding to the parent element, `margin-top` of the parent and `margin-top` of the child element would be separated. Therefore the margin of the child would be included in the height of the parent box. – Hashem Qolami Feb 24 '15 at 22:57
  • some other links http://www.sitepoint.com/web-foundations/collapsing-margins/ and http://www.w3.org/TR/CSS2/box.html to add to previous comment :) have fun – G-Cyrillus Feb 24 '15 at 23:03

1 Answers1

1

As Hashem pointed out in a comment, the problem is the collapsing margins. The parent div has nothing between it and its parent, so the margins of the div's child h1 become its margins. If the div has a padding or a border, this prevents the margin collapse.

In order to make the margins not collapse, we can use the :before and :after pseudo-elements on the parent div:

#a1:before, #a1:after{
    content: '';
    display: table;
}

This will slightly alter the position of the child element, but it will keep the height consistent regardless of padding and cause the child margins to be included in div.offsetHeight

I found this technique in another answer here.

updated JSFiddle

Community
  • 1
  • 1
Chris Middleton
  • 5,654
  • 5
  • 31
  • 68