6

According to JQuery docs outerHeight(true) function returns the total height of the element including padding border and margins. I ran into a case where this promise seems to be broken. Here is a repro.

here is the html:

outer div height = <span id="div-target"></span><br/>
ul height (including margins) = <span id="ul-target"></span><br/><br/>
<div show-height-in='div-target'>
    <ul show-height-in='ul-target'>here</ul>
</div>

and the javascript:

var app = angular.module('application',[]);
app.directive('showHeightIn', function($log){
    return function(scope, element,attrs) {
        $('#' + attrs.showHeightIn).text($(element).outerHeight(true));
    }
});
angular.bootstrap(document, ['application']);

in this example the <ul> element uses the default style which adds 16px top and bottom margins. This brings outerHeight of the <ul> to 52px.

Now the parent <div> element shows outerHeight(true) only 20px - which does not include either margin.

This question on SO talks about collapsing margins, and I understand the explanation - to a degree. My questions though is not why margins are not included.

My questions is how can I determine the height of the div as rendered. Apparently outerHeight(true) in certain cases is incorrect.

@Gaby: changing element style is not the only way to do that. You can also add 0 height block items before and after. But I am not looking for a way to prevent margin collapsing. I am looking for a universal way to determine the total height occupied by the element. I need this to avoid limitations on usage of my ng-scroll directive.

Community
  • 1
  • 1
mfeingold
  • 7,094
  • 4
  • 37
  • 43

2 Answers2

12

Adding overflow:auto on the div element will disable margin collapsing and the value will be correctly calculated.

Demo at http://jsfiddle.net/hdReR/2/

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
1

You should separately calculate the container height without margins, then add the max value between the container top+bottom margin and the sum of first-child's margin-top and last-child's margin-bottom.

var mVert = parseInt($('#container').css('margin-top'))
    + parseInt($('#container').css('margin-bottom'));
var mVertChildren = parseInt($('#container').children().first().css('margin-top'))
    + parseInt($('#container').children().last().css('margin-bottom'));

var realHeight = $('#container').outerHeight(false)
    + (mVert > mVertChildren ? mVert : mVertChildren);

Demo at http://jsfiddle.net/j67phdpd/2/

Alessio Gaeta
  • 5,670
  • 1
  • 16
  • 26
  • 1
    This is really useful, but unfortunately not correct in all situations. See [this fork](http://jsfiddle.net/3v7t4tq0/) of your fiddle. I think you need to handle each collapse of margins individually. – Danimal Jul 22 '15 at 11:52