jQuery:在jQuery中获取隐藏元素的高度

时间:2010-02-27 00:52:43

标签: jquery html css

我需要获取隐藏在div中的元素的高度。现在我显示div,获得高度,并隐藏父div。这看起来有点傻。还有更好的方法吗?

我正在使用jQuery 1.4.2:

$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();

15 个答案:

答案 0 :(得分:175)

你可以做这样的事情,虽然有点hacky,如果它已经是绝对的话,请忘记position

var previousCss  = $("#myDiv").attr("style");

$("#myDiv").css({
    position:   'absolute', // Optional if #myDiv is already absolute
    visibility: 'hidden',
    display:    'block'
});

optionHeight = $("#myDiv").height();

$("#myDiv").attr("style", previousCss ? previousCss : "");

答案 1 :(得分:90)

我遇到了隐藏元素宽度的同样问题,所以我写了这个插件调用jQuery Actual来修复它。而不是使用

$('#some-element').height();

使用

$('#some-element').actual('height');

将为隐藏元素提供正确的值,或者元素具有隐藏的父元素。

完整文档请参阅here。页面中还有一个演示包含。

希望这有帮助:)

答案 2 :(得分:38)

您正在混淆两种CSS样式,display stylevisibility style

如果通过设置visibility css样式来隐藏元素,那么无论元素是否可见都应该能够获得高度,因为元素仍占用页面空间

如果通过将显示css样式更改为“none”来隐藏元素,则该元素不会在页面上占用空间,并且您必须为其提供一种显示样式,这将导致元素在某些内容中呈现空间,此时,你可以得到高度。

答案 3 :(得分:28)

我实际上有时会采取一些技巧来解决这个问题。我开发了一个jQuery滚动条小部件,如果可滚动内容是隐藏的标记的一部分,我遇到了我不知道的问题。这是我做的:

// try to grab the height of the elem
if (this.element.height() > 0) {
    var scroller_height = this.element.height();
    var scroller_width = this.element.width();

// if height is zero, then we're dealing with a hidden element
} else {
    var copied_elem = this.element.clone()
                      .attr("id", false)
                      .css({visibility:"hidden", display:"block", 
                               position:"absolute"});
    $("body").append(copied_elem);
    var scroller_height = copied_elem.height();
    var scroller_width = copied_elem.width();
    copied_elem.remove();
}

这在很大程度上起作用,但是有一个明显的问题可能会出现。如果您要克隆的内容使用CSS进行样式设置,其中包含对其规则中父标记的引用,则克隆的内容将不包含相应的样式,并且可能会略有不同的度量。为了解决这个问题,您可以确保要克隆的标记应用了CSS规则,但不包含对父标记的引用。

此外,我的滚动窗口小部件并没有出现这种情况,但要获得克隆元素的适当高度,您需要将宽度设置为父元素的相同宽度。在我的例子中,CSS宽度总是应用于实际元素,所以我不必担心这个,但是,如果元素没有应用宽度,你可能需要做一些递归遍历元素的DOM祖先以找到适当的父元素的宽度。

答案 4 :(得分:12)

进一步探讨尼克的回答:

$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").css({'position':'static','visibility':'visible', 'display':'none'});

我发现这样做更好:

$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").removeAttr('style');

设置CSS属性会将它们插入内联,这将覆盖CSS文件中的任何其他属性。通过删除HTML元素上的style属性,一切都恢复正常并仍然隐藏,因为它首先被隐藏。

答案 5 :(得分:12)

进一步构建用户Nick的答案和用户hitautodestruct的JSBin插件,我创建了一个类似的jQuery插件,它检索宽度和高度,并返回包含这些值的对象。

可以在这里找到: http://jsbin.com/ikogez/3/

更新

我已经完全重新设计了这个小小的插件,因为事实证明之前的版本(如上所述)在真正的生活环境中并不真正可用,在这些环境中发生了大量的DOM操作。

这完美地运作:

/**
 * getSize plugin
 * This plugin can be used to get the width and height from hidden elements in the DOM.
 * It can be used on a jQuery element and will retun an object containing the width
 * and height of that element.
 *
 * Discussed at StackOverflow:
 * http://stackoverflow.com/a/8839261/1146033
 *
 * @author Robin van Baalen <robin@neverwoods.com>
 * @version 1.1
 * 
 * CHANGELOG
 *  1.0 - Initial release
 *  1.1 - Completely revamped internal logic to be compatible with javascript-intense environments
 *
 * @return {object} The returned object is a native javascript object
 *                  (not jQuery, and therefore not chainable!!) that
 *                  contains the width and height of the given element.
 */
$.fn.getSize = function() {    
    var $wrap = $("<div />").appendTo($("body"));
    $wrap.css({
        "position":   "absolute !important",
        "visibility": "hidden !important",
        "display":    "block !important"
    });

    $clone = $(this).clone().appendTo($wrap);

    sizes = {
        "width": $clone.width(),
        "height": $clone.height()
    };

    $wrap.remove();

    return sizes;
};

答案 6 :(得分:4)

您还可以使用负边距而不是使用display:none来将隐藏的div放在屏幕上,而不是使用display:none,就像文本缩进图像替换技术一样。

例如

position:absolute;
left:  -2000px;
top: 0;

这样,height()仍然可用。

答案 7 :(得分:2)

根据Nick Craver的解决方案,设置元素的可见性可以获得准确的尺寸。我经常使用这个解决方案。但是,不得不手动重置样式,我发现这很麻烦,因为通过开发修改元素在我的CSS中的初始定位/显示,我经常忘记更新相关的javascript代码。以下代码不会重置每个说明的样式,但会删除javascript添加的内联样式:

$("#myDiv")
.css({
    position:   'absolute',
    visibility: 'hidden',
    display:    'block'
});

optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();

$("#myDiv").attr('style', '');

这里唯一的假设是不能有其他内联样式,否则它们也会被删除。然而,这里的好处是元素的样式返回到它们在css样式表中的样式。因此,您可以将其编写为传递元素的函数,并返回高度或宽度。

我发现通过js设置内联样式的另一个问题是,当通过css3处理转换时,你会被迫调整你的样式规则的权重,使其比内联样式更强,这有时会让人感到沮丧。 / p>

答案 8 :(得分:2)

我试图找到隐藏元素的工作函数,但我意识到CSS比每个人都想象的要复杂得多。 CSS3中有许多新的布局技术可能不适用于所有先前的答案,如灵活的框,网格,列或复杂父元素内的元素。

flexibox示例 enter image description here

我认为唯一可持续的&amp;简单的解决方案是实时渲染。那时,浏览器应该为您提供正确的元素大小

可悲的是,JavaScript在显示或隐藏元素时不提供任何直接事件通知。但是,我创建了一些基于DOM Attribute Modified API的函数,当元素的可见性发生变化时,它将执行回调函数。

$('[selector]').onVisibleChanged(function(e, isVisible)
{
    var realWidth = $('[selector]').width();
    var realHeight = $('[selector]').height();

    // render or adjust something
});

有关详细信息,请访问我的项目GitHub。

https://github.com/Soul-Master/visible.event.js

演示:http://jsbin.com/ETiGIre/7

答案 9 :(得分:1)

根据定义,元素只有在可见的情况下才有高度。

好奇:为什么你需要一个隐藏元素的高度?

另一种方法是通过将元素放在后面(使用z-index)覆盖某种元素来有效地隐藏元素。

答案 10 :(得分:1)

在我的情况下,我也有一个隐藏的元素阻止我获取高度值,但它不是元素本身而是其中一个父母...所以我只是检查我的一个插件到看看它是否隐藏,否则找到最近的隐藏元素。这是一个例子:

var $content = $('.content'),
    contentHeight = $content.height(),
    contentWidth = $content.width(),
    $closestHidden,
    styleAttrValue,
    limit = 20; //failsafe

if (!contentHeight) {
    $closestHidden = $content;
    //if the main element itself isn't hidden then roll through the parents
    if ($closestHidden.css('display') !== 'none') { 
        while ($closestHidden.css('display') !== 'none' && $closestHidden.size() && limit) {
            $closestHidden = $closestHidden.parent().closest(':hidden');
            limit--;
        }
    }
    styleAttrValue = $closestHidden.attr('style');
    $closestHidden.css({
        position:   'absolute',
        visibility: 'hidden',
        display:    'block'
    });
    contentHeight = $content.height();
    contentWidth = $content.width();

    if (styleAttrValue) {
        $closestHidden.attr('style',styleAttrValue);
    } else {
        $closestHidden.removeAttr('style');
    }
}

事实上,这是Nick,Gregory和Eyelidlessness的回应合并给你使用Gregory的改进方法,但是如果你想要放回样式属性中的某些内容,则使用这两种方法,并寻找父元素。

我对解决方案的唯一抱怨是,通过父母的循环并不完全有效。

答案 11 :(得分:1)

一种解决方法是在要获得高度的元素外部创建父div,应用高度“0”并隐藏任何溢出。接下来,获取子元素的高度并删除父元素的overflow属性。

var height = $("#child").height();
// Do something here
$("#parent").append(height).removeClass("overflow-y-hidden");
.overflow-y-hidden {
  height: 0px;
  overflow-y: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="parent" class="overflow-y-hidden">
  <div id="child">
    This is some content I would like to get the height of!
  </div>
</div>

答案 12 :(得分:0)

这是我编写的一个脚本,用于处理隐藏元素的所有jQuery维度方法,甚至是隐藏父元素的后代。请注意,当然,使用它会有性能损失。

// Correctly calculate dimensions of hidden elements
(function($) {
    var originals = {},
        keys = [
            'width',
            'height',
            'innerWidth',
            'innerHeight',
            'outerWidth',
            'outerHeight',
            'offset',
            'scrollTop',
            'scrollLeft'
        ],
        isVisible = function(el) {
            el = $(el);
            el.data('hidden', []);

            var visible = true,
                parents = el.parents(),
                hiddenData = el.data('hidden');

            if(!el.is(':visible')) {
                visible = false;
                hiddenData[hiddenData.length] = el;
            }

            parents.each(function(i, parent) {
                parent = $(parent);
                if(!parent.is(':visible')) {
                    visible = false;
                    hiddenData[hiddenData.length] = parent;
                }
            });
            return visible;
        };

    $.each(keys, function(i, dimension) {
        originals[dimension] = $.fn[dimension];

        $.fn[dimension] = function(size) {
            var el = $(this[0]);

            if(
                (
                    size !== undefined &&
                    !(
                        (dimension == 'outerHeight' || 
                            dimension == 'outerWidth') &&
                        (size === true || size === false)
                    )
                ) ||
                isVisible(el)
            ) {
                return originals[dimension].call(this, size);
            }

            var hiddenData = el.data('hidden'),
                topHidden = hiddenData[hiddenData.length - 1],
                topHiddenClone = topHidden.clone(true),
                topHiddenDescendants = topHidden.find('*').andSelf(),
                topHiddenCloneDescendants = topHiddenClone.find('*').andSelf(),
                elIndex = topHiddenDescendants.index(el[0]),
                clone = topHiddenCloneDescendants[elIndex],
                ret;

            $.each(hiddenData, function(i, hidden) {
                var index = topHiddenDescendants.index(hidden);
                $(topHiddenCloneDescendants[index]).show();
            });
            topHidden.before(topHiddenClone);

            if(dimension == 'outerHeight' || dimension == 'outerWidth') {
                ret = $(clone)[dimension](size ? true : false);
            } else {
                ret = $(clone)[dimension]();
            }

            topHiddenClone.remove();
            return ret;
        };
    });
})(jQuery);

答案 13 :(得分:0)

如果您之前已经在页面上显示过该元素,则可以直接从DOM元素中获取高度(可以使用.get(0)在jQuery中获取),因为即使元素是隐藏的:

$('.hidden-element').get(0).height;

宽度相同:

$('.hidden-element').get(0).width;

(感谢Skeets O&#39; Reilly进行更正)

答案 14 :(得分:-5)

$('#idOfElement').height();

//找到身高