How to calculate the height of an element, taking into account the collapsed fields

I want to calculate the total "height" of a div element, taking into account the effect of collapsing margins due to child elements, that is, the total space that the div element occupies in the document. I find it difficult to think of a better algorithm / approach for this.

Consider, for example, a div element with margin-top of 10px and a height of 50px . This div element has a child element <h2> that has margin-top of 20px . Then the div margin will crash and the actual "height" this div will be 70px . However, using jQuery methods, we can get the height div without considering its margins or by counting it 10 pixel margin , which would give us the wrong value:

 $(elem).outerHeight() // 50 $(elem).outerHeight(true) // 60 

To illustrate my point here is the jsfiddle I created with two examples.

My best guess at the moment is that we have to somehow sort through all the children of the div and calculate the height of the top and bottom margins. According to what I understand from the W3C spec, we can skip this iteration for the top margin if the target div has top-border-width or top-padding . The same goes for the bottom margin .

Any help would be greatly appreciated. Thanks!

EDIT:

One (ugly) solution I was thinking of was wrapping the target div element in another div. Then we quickly add and remove the transparent borderTop and borderBottom to the wrapper div, measuring its height between them. Borders will force the edge of the wrapping div to not fall off with its child fields. Something like that:

 var collapsedHeight = function( target ) { var $wrapper = $('<div />'), $target = $(target); $wrapper.insertAfter($target); $target.appendTo($wrapper); $wrapper.css({ borderTop: '1px solid transparent', borderBottom: '1px solid transparent' }); var result = $wrapper.outerHeight() - 2; $target.insertAfter($wrapper); $wrapper.remove(); return result; }; 

I made jsFiddle for it here .

+4
source share
3 answers

Consider this hack:

 $( elem ).wrap( '<div style="border:1px solid transparent;"></div>' ).parent().height() 

The above expression returns 70 , what do you want, right?

So, the idea is to wrap your element in a DIV that has a transparent set of borders. This border prevents the fields of your element from interfering with the fields of the previous and next brother.

Once you get the height value, you can expand your element ...

+5
source

For a solution that is not related to DOM manipulation, you can achieve the same effect by adding an addition to the item being measured and then deleting it after.

 function getRealHeight(elementP) { var element = (elementP instanceof jQuery)? elementP : $(element), padTop = parseInt(element.css('paddingTop')), padBottom = parseInt(element.css('paddingBottom')), offset, height; if (padTop == 0 || padBottom == 0) { offset = 0; if (padTop == 0) { element.css('paddingTop', 1); offset += 1; } if (padBottom == 0) { element.css('paddingBottom', 1); offset += 1; } height = (element.outerHeight(true) - offset); if (padTop == 0) { element.css('paddingTop', ''); } if (padBottom == 0) { element.css('paddingBottom', ''); } } else { height = element.outerHeight(true); } return height; } 

Bonus of this decision; You can get around the top of the wrapper / spread.

0
source

You can make it a jQuery plugin:

 (function ($) { $.fn.extend({ //plugin name - realHeight realHeight: function (options) { //Settings list and the default values var defaults = {}; var options = $.extend(defaults, options); function getRealHeight(elementP) { var element = (elementP instanceof jQuery) ? elementP : $(element), padTop = parseInt(element.css('paddingTop')), padBottom = parseInt(element.css('paddingBottom')), offset, height; if (padTop == 0 || padBottom == 0) { offset = 0; if (padTop == 0) { element.css('paddingTop', 1); offset += 1; } if (padBottom == 0) { element.css('paddingBottom', 1); offset += 1; } height = (element.outerHeight(true) - offset); if (padTop == 0) { element.css('paddingTop', ''); } if (padBottom == 0) { element.css('paddingBottom', ''); } } else { height = element.outerHeight(true); } return height; } return getRealHeight($(this)); } }); })(jQuery); 
0
source

All Articles