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

时间:2011-10-26 23:05:22

标签: javascript jquery css

我想计算一个div元素的总“高度”,考虑到collapsed margins的影响,因为子元素,即div元素在文档中占用的总空间。我很难想到最好的算法/方法来做到这一点。

例如,考虑一个margin-top 10pxheight 50px的div元素。此div元素的子<h2>元素的margin-top20px。然后div的{​​{1}}将崩溃,margin的实际"height"将为div。但是,使用jQuery方法,我们只能获得70px的{​​{1}}而不考虑height,或者考虑div像素margins给我们错误的价值:

10

为了帮助说明我的观点,here是我用两个例子创建的jsfiddle。

我现在最好的猜测是我们必须以某种方式迭代div的所有孩子并计算最高的上下边距。 根据我从W3C规范中理解的内容,如果目标div具有margin$(elem).outerHeight() // 50 $(elem).outerHeight(true) // 60 ,我们可以跳过顶部margin的此迭代。同样适用于底部top-border-width

非常感谢任何帮助。谢谢!

修改

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

top-padding

我为它制作了一个jsFiddle here

3 个答案:

答案 0 :(得分:5)

考虑一下这个黑客:

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

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

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

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

答案 1 :(得分:0)

对于不涉及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;
}

此解决方案的奖励;你可以回避包裹/解包的开销。

答案 2 :(得分:0)

你可以把它变成一个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);