ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我正在使用 jQuery 1.4.2:

$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
我不同意蒂姆。使用此解决方案,显示可能会闪烁,因为您实际上是在显示项目然后将其隐藏。即使 Nicks 解决方案更加复杂,它也没有机会闪烁显示,因为父 div 从未显示。
我刚刚发现这个 hack 不适用于任何版本的 IE。
哈利,实际上你发现的是你的代码在 IE 中不起作用,而不是这个解决方案。去调试你的代码:)

A
Antti29

你可以做这样的事情,虽然有点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 : "");

我将上面的代码合并到一个 jQ 插件 jsbin.com/ihakid/2 中。我还使用一个类并检查父母是否也被隐藏。
+1 这很好用。请记住,元素的父元素也必须显示。这让我困惑了几分钟。此外,如果元素是 position:relative,您当然希望在后面设置它而不是 static
使用此方法时,目标元素通常会改变形状。因此,在绝对定位时获取 div 的高度和/或宽度可能不是很有用。
@Gavin 这可以防止回流计算和对用户的任何闪烁,因此它既便宜又不那么干扰。
@hitautodestruct,我已经修改了你的查询插件来检查这个只有元素实际上是隐藏的。 jsbin.com/ihakid/58
C
Community

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

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

利用

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

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

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

希望这有帮助:)


是的,它有帮助! 2015,它仍然有帮助。您在实际网站上说“旧版本的 jquery” - 但是 - 在 v2.1.3 中仍然需要它,至少在我的情况下是这样。
谢谢!我使用这个插件来读取和设置最初隐藏在手风琴中的元素的高度(这是动态完成的)
很棒的插件!当设置为 100% 时,我尝试了一切以获取模态中 div 的宽度,但没有任何效果。在 5 秒内完成设置并完美运行!
@ben 链接已损坏。
B
Brian

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

如果通过设置可见性 css 样式隐藏元素,那么无论元素是否可见,您都应该能够获取高度,因为元素仍然占用页面上的空间。

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


谢谢你。我的问题涉及表格单元格,将 visibility 设置为 hidden 并没有解决我的问题,但它给了我设置 position: fixed; top: 100% 的想法,它就像一个魅力!
现在我明白了为什么它的高度没有用 display:none 元素显示。非常感谢精彩的解释。
c
casperOne

实际上,我有时会采取一些技巧来处理这个问题。我开发了一个 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 祖先以找到适当的父元素的宽度。


不过,这有一个有趣的问题。如果元素已经是块元素,则克隆将采用整个主体宽度(主体填充或边距除外),这与容器内的大小不同。
R
Robin van Baalen

在用户 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;
};

你的代码不正确。您需要 sizes = {"width": $wrap.width(), "height": $wrap.height()}; this 指的是原始项目,它是不可见的。
@jackJoe 我已经使用此代码很长一段时间没有问题。充其量我会说我需要 $clone.width() 而不是“this”。不是 $wrap 因为我想要包装内元素的大小。例如,包装器可能是 10000x10000 像素,而我要测量的元素仍然是 30x40 像素。
即使以 $wrap 为目标也可以(至少在我的测试中)。我尝试使用 this 并且显然它不会捕获大小,因为 this 仍然指的是隐藏元素。
G
Gregory Bolkenstijn

进一步建立尼克的回答:

$("#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 属性,一切都恢复正常并且仍然隐藏,因为它最初是隐藏的。


$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'}); optionHeight = $("#myDiv").height(); $("#myDiv").css({'position':'','visibility':'', 'display':''});
...除非您已经在元素上具有内联样式。如果您使用 jQuery 隐藏元素,就会出现这种情况。
v
vaughanos

您还可以使用负边距将隐藏的 div 放置在屏幕之外,而不是使用 display:none,这很像文本缩进图像替换技术。

例如。

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

这样 height() 仍然可用。


u
user229044

我试图找到隐藏元素的工作函数,但我意识到 CSS 比大家想象的要复杂得多。 CSS3 中有许多新的布局技术可能不适用于所有以前的答案,例如灵活的框、网格、列甚至复杂父元素中的元素。

https://i.stack.imgur.com/F1PWq.png

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

遗憾的是,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 行 here),而可见性更改也可能由 class 属性的更改引起。
你是对的。正确的语句应该是 e.attributeName !== 'style' && e.attributeName !== 'className'
P
Prusprus

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

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

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

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

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

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


其他 JavaScript 功能也经常使用内联样式,因此通常不需要完全重置样式。
c
cletus

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

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

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


我需要一个元素的高度,它恰好在我想要它的高度时被隐藏。我正在构建一个插件,我需要在初始化时收集一些数据
另一个原因是使用 javascript 将可能尚不可见的事物居中
@cletus如果您只是好奇地写评论,那通常是前端编码中获取隐藏元素大小的情况。
m
marksyzm

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

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 的改进方法,但同时使用这两种方法,以防您想要放回样式属性中的某些内容,并寻找一个父元素。

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


M
Matt

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

var height = $("#child").height(); // 在这里做一些事情 $("#parent").append(height).removeClass("overflow-y-hidden"); .overflow-y-hidden { 高度:0px;溢出-y:隐藏; }

这是一些我想得到高度的内容!


c
casperOne

这是我编写的一个脚本,用于处理隐藏元素的所有 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);

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

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

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

宽度相同:

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

(感谢 Skeets O'Reilly 的纠正)


返回 undefined
很确定这只有在您之前已经在页面上显示过元素时才有效。对于一直为 display='none' 的元素,这将不起作用。