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


249

我需要获取处于隐藏的div内的元素的高度。现在,我显示div,获取高度,并隐藏父div。这似乎有点愚蠢。有没有更好的办法?

我正在使用jQuery 1.4.2:

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

42
+1您的示例解决方案实际上比任何答案都更好。
蒂姆·桑特福德

9
我不同意蒂姆。使用此解决方案,由于您实际上是在显示项目然后将其隐藏,因此显示可能会闪烁。即使Nicks解决方案比较复杂,它也不会闪烁显示,因为永远不会显示父div。
汉弗莱



5
哈里,实际上您发现您的代码无法在IE中运行,而不是这种解决方案。去调试你的代码:)
Gavin

Answers:


181

您可以执行以下操作,虽然有点怪异,但请记住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 : "");

17
我将上面的代码合并到一个jQ插件jsbin.com/ihakid/2中。我还使用一个类,并检查父项是否也被隐藏。
hitautodestruct

3
+1很棒。请记住,还必须显示元素的父项。这让我困惑了几分钟。另外,如果元素为position:relative,则当然要在之后设置而不是static
Michael Mior 2012年

6
使用此方法时,目标元素通常可以更改形状。因此,在绝对定位时获取div的高度和/或宽度可能不是很有用。
杰里米·里基茨

2
@Gavin这样可以防止回流计算和对用户的闪烁,因此既便宜又不那么麻烦。
尼克·克拉弗

2
@hitautodestruct,我已经修改了您的查询插件,以检查是否只有该元素实际上是隐藏的。 jsbin.com/ihakid/58
Prasad

96

我遇到了隐藏元素宽度的相同问题,因此我编写了此插件调用jQuery Actual来修复它。而不是使用

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

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

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

完整文档,请参见此处。页面中还包含一个演示。

希望这个帮助:)


3
是的,它有帮助!2015年,它仍然有帮助。您在实际网站上说“ jquery的较旧版本”-但是-在v2.1.3中仍然需要,至少在我看来是这样。
LpLrich 2015年

谢谢!我使用此插件读取并设置了最初隐藏在手风琴中的元素的高度(这是动态完成的)
alds

很棒的插件!当设置为100%并且没有任何效果时,我尝试了所有方法来获取模态内div的宽度。在5秒钟内完成设置并完美运行!
Craig Howell

@ben链接已断开。
萨钦·普拉萨德

39

您正在混淆两种CSS样式,即显示样式可见性样式

如果通过设置可见性css样式隐藏了元素,则无论元素是否可见,您都应该能够获得高度,因为该元素仍在页面上占据空间

如果通过将display css样式更改为“ none”来隐藏该元素,则该元素不会在页面上占用空间,并且您将不得不给它一种显示样式,这将导致该元素在某个空间处呈现。哪一点就可以得到高度。


谢谢你 我的问题涉及一个表格单元,并且设置visibilityhidden并不能解决我的问题,但这给了我进行设置的想法position: fixed; top: 100%,它的工作原理很吸引人!
Jayen 2014年

现在,我了解了为什么没有用display:none元素显示其高度的原因。非常感谢您的精彩解释。
FrenkyB

30

实际上,我有时会采取一些技巧来解决这个问题。我开发了一个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规则,其中不包括对父标记的引用。

另外,我的滚动器小部件并没有解决这个问题,但是要获得适当的克隆元素高度,您需要将宽度设置为与父元素相同的宽度。就我而言,CSS宽度始终应用于实际元素,因此我不必担心这一点,但是,如果元素没有对其应用宽度,则可能需要进行某种递归遍历元素的DOM祖先以找到适当的父元素的宽度。


但是,这有一个有趣的问题。如果该元素已经是一个块元素,则clone将采用整个主体宽度(主体填充或边距除外),该宽度与容器内部的大小不同。
Meligy 2012年

16

在用户Nick的答案和JSBin上的用户hitautodestruct的插件的基础上,我创建了一个类似的jQuery插件,该插件可同时检索width和height并返回包含这些值的对象。

可以在这里找到: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;
};

您的代码不正确。你需要sizes = {"width": $wrap.width(), "height": $wrap.height()};this是指原来的项目,这是不可见的。
jackJoe16年

@jackJoe我已经使用此代码一段时间了,没有问题。充其量我会说我需要$ clone.width()而不是'this'。不是$ wrap,因为我想要包装内的元素大小。包装器可能是10000x10000px,而我要测量的元素仍然是30x40px。
罗宾·范·巴伦

即使定位也是$wrap可以的(至少在我的测试中如此)。我尝试使用this,显然它无法捕捉大小,因为它this仍然引用隐藏的元素。
jackJoe16年

1
感谢@jackJoe,我现在更新了代码示例。
罗宾·范·巴伦

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属性,所有内容都恢复了正常,并且仍然隐藏,因为它首先隐藏了。


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

9
...除非您已经在元素上具有内联样式。如果您使用jQuery隐藏该元素,则将是这种情况。
Muhd

4

您也可以使用负边距将隐藏的div置于屏幕之外,而不是使用display:none,就像文本缩进图像替换技术一样。

例如。

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

这样height()仍然可用。


3

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

flexibox示例 在此处输入图片说明

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

可悲的是,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


感谢您的回答。它也启发了我也使用MutationObservers。但是请注意,您的库仅检查由style属性更改引起的可见性更改(请参见此处的第59行),而可见性更改也可能是由属性更改引起的class
Ashraf Sabry 2014年

你是对的。正确的说法应该是e.attributeName == '风格' && e.attributeName == '的className'!
Soul_Master

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处理过渡时,您不得不适应于更改样式规则的权重,使其比内联样式更强,这有时会令人沮丧。


1

根据定义,元素只有在可见时才具有高度。

只是好奇:为什么需要隐藏元素的高度?

一种替代方法是通过将元素放置在某种类型的叠加层之后(使用z-index)来有效地隐藏它。


1
我需要一个元素的高度,在我想要它的高度的时候碰巧被隐藏了。我正在构建一个插件,我需要在初始化时收集一些数据
mkoryak 2010年

2
另一个原因是使用可能尚不可见的javascript将内容居中
Simon_Weaver

@cletus如果您只是好奇地写评论,那么在前端编码中通常会得到隐藏元素的大小。
Rantiev

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的改进方法,但是要同时使用两种方法,以防样式属性中有您想放回的东西并寻找父元素。

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


1

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

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>


0

这是我编写的脚本,用于处理jQuery的所有隐藏元素,甚至隐藏父级后代的Dimension方法。请注意,使用此功能当然会对性能产生影响。

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

双眼失明的答案看起来很适合我的需求,但不适用于我正在运行的jQuery:1.3.2它导致jQuery抛出this.clone(或非常接近的东西)不是函数。有人对如何解决有任何想法吗?

0

如果您之前已经在页面上显示了该元素,则可以直接从DOM元素直接获取高度(在jQuery中可以通过.get(0)到达),因为即使隐藏了该元素,它的高度也会被设置:

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

宽度相同:

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

(感谢Skeets O'Reilly的更正)


返回undefined
杰克·威尔逊

1
可以肯定的是,只有在先前已经在页面上显示了元素的情况下,此方法才有效。对于一直存在的元素,display='none'它将不起作用。
双向飞碟,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.