考虑折叠边距,如何计算元素的高度

我想计算div元素的总“高度”,考虑由于子元素而导致的折叠 边距的影响,即div元素在文档中占据的总空间。 我很难想到最好的算法/方法来做到这一点。

例如,考虑一个div元素,其margin-top10pxheight50px 。 这个div元素有一个子

元素,其margin-top20px 。 然后divmargin将崩溃,该div的实际"height"将为70px 。 但是,使用jQuery方法,我们只能在不考虑它的margins情况下获得divheight ,或者考虑它的10像素margin会给我们错误的值:

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

为了帮助说明我的观点, 这里有一个我用两个例子创建的jsfiddle。

我现在最好的猜测是我们必须以某种方式迭代div的所有子项并计算最高的上下边距。 根据我从W3C规范中理解的,如果目标div具有top-border-widthtop-padding ,我们可以跳过顶部margin此迭代。 同样适用于底部margin

任何帮助将不胜感激。 谢谢!

编辑:

我想到的一个(丑陋)解决方案是将目标div元素包装在另一个div中。 然后,我们快速添加和删除透明borderTop和borderBottom到包装div,测量它们之间的高度。 边界将迫使包装div的边缘不会随着孩子的边缘而崩溃。 像这样的东西:

 var collapsedHeight = function( target ) { var $wrapper = $('
'), $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; };

我在这里做了一个jsFiddle。

考虑一下这个黑客:

 $( elem ).wrap( '
' ).parent().height()

上面的表达式返回70 ,这是你想要的,对吗?

因此,我们的想法是将您的元素包装在具有透明边框集的DIV中。 此边框将阻止元素的边距干扰其上一个和下一个兄弟的边距。

获得高度值后,您可以打开元素…

对于不涉及DOM操作的解决方案,您可以通过向正在测量的元素添加填充然后将其删除来实现相同的效果。

 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; } 

这个解决方案的好处; 你可以回避包裹/解包的开销。

你可以把它变成一个jQuery插件:

 (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);