jQuery - 获取元素不可见时的宽度(显示:无)

发布于 2024-08-05 22:02:15 字数 717 浏览 5 评论 0原文

看起来在 jQuery 中,当元素不可见时 width() 返回 0。有道理,但我需要获取表格的宽度,以便在显示父级之前设置父级的宽度。

如下所述,父级中有文本,这使得父级倾斜并且看起来很糟糕。我希望父级的宽度与表格一样宽并且文本自动换行。

<div id="parent">
    Text here ... Can get very long and skew the parent
    <table> ... </table>
    Text here too ... which is why I want to shrink the parent based on the table
</div>

CSS:

#parent
{
    display: none;
}

Javascript:

var tableWidth = $('#parent').children('table').outerWidth();
if (tableWidth > $('#parent').width())
{
    $('#parent').width(tableWidth);
}

tableWidth 总是返回 0,因为它不可见(这是我的猜测,因为它在可见时给了我一个数字)。有没有办法在不使父级可见的情况下获取表格的宽度?

It seems like in jQuery when an element is not visible width() returns 0. Makes sense, but I need to get the width of a table in order to set the width of the parent before I show the parent.

As noted below, there is text in the parent, that makes the parent skew and look nasty. I want the parent to be only as wide as the table and have the text wrap.

<div id="parent">
    Text here ... Can get very long and skew the parent
    <table> ... </table>
    Text here too ... which is why I want to shrink the parent based on the table
</div>

CSS:

#parent
{
    display: none;
}

Javascript:

var tableWidth = $('#parent').children('table').outerWidth();
if (tableWidth > $('#parent').width())
{
    $('#parent').width(tableWidth);
}

tableWidth always returns 0 since it is not visible (is my guess since it gives me a number when visible). Is there a way to get the width of the table without making the parent visible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

堇年纸鸢 2024-08-12 22:02:16

如果您需要隐藏某些内容的宽度,并且无论出于何种原因都无法取消隐藏它,您可以克隆它,更改 CSS,使其显示在页面之外,使其不可见,然后测量它。如果随后将其隐藏并删除,用户将一无所知。

这里的其他一些答案只是隐藏了可见性,这有效,但它会在您的页面上占据一小部分空白。

例子:

$itemClone = $('.hidden-item').clone().css({
        'visibility': 'hidden',
        'position': 'absolute',
        'z-index': '-99999',
        'left': '99999999px',
        'top': '0px'
    }).appendTo('body');
var width = $itemClone.width();
$itemClone.remove();

If you need the width of something that's hidden and you can't un-hide it for whatever reason, you can clone it, change the CSS so it displays off the page, make it invisible, and then measure it. The user will be none the wiser if it's hidden and deleted afterwards.

Some of the other answers here just make the visibility hidden which works, but it will take up a blank spot on your page for a fraction of a second.

Example:

$itemClone = $('.hidden-item').clone().css({
        'visibility': 'hidden',
        'position': 'absolute',
        'z-index': '-99999',
        'left': '99999999px',
        'top': '0px'
    }).appendTo('body');
var width = $itemClone.width();
$itemClone.remove();
顾冷 2024-08-12 22:02:16

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

灵活盒示例
在此处输入图像描述

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

遗憾的是,JavaScript 不提供任何直接事件来通知元素何时显示或隐藏。但是,我创建了一些基于 DOM 属性修改 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

I try to find working function for hidden element but I realize that CSS is much complex than everyone think. There are a lot of new layout techniques in CSS3 that might not work for all previous answers like flexible box, grid, column or even element inside complex parent element.

flexibox example
enter image description here

I think the only sustainable & simple solution is real-time rendering. At that time, browser should give you that correct element size.

Sadly, JavaScript does not provide any direct event to notify when element is showed or hidden. However, I create some function based on DOM Attribute Modified API that will execute callback function when visibility of element is changed.

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

    // render or adjust something
});

For more information, Please visit at my project GitHub.

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

demo: http://jsbin.com/ETiGIre/7

请爱~陌生人 2024-08-12 22:02:16

在获取宽度之前使父显示器显示,然后获取宽度,最后使父显示器隐藏。就像下面这样

$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
 $('#parent').hide();
if (tableWidth > $('#parent').width())
{
    $('#parent').width() = tableWidth;
}

Before take the width make the parent display show ,then take the width and finally make the parent display hide. Just like following

$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
 $('#parent').hide();
if (tableWidth > $('#parent').width())
{
    $('#parent').width() = tableWidth;
}
倾城月光淡如水﹏ 2024-08-12 22:02:16

一种解决方案(尽管并非在所有情况下都有效)是通过将不透明度设置为 0 来隐藏元素。完全透明的元素将具有宽度。

缺点是该元素仍然会占用空间,但这在所有情况下都不会成为问题。

例如:

$(img).css("opacity", 0)  //element cannot be seen
width = $(img).width()    //but has width

One solution, though it won't work in all situations, is to hide the element by setting the opacity to 0. A completely transparent element will have width.

The draw back is that the element will still take up space, but that won't be an issue in all cases.

For example:

$(img).css("opacity", 0)  //element cannot be seen
width = $(img).width()    //but has width
一场春暖 2024-08-12 22:02:16

大多数解决方案忽略的最大问题是,CSS 经常根据元素在 html 中的作用域来更改元素的宽度。

如果我要通过将元素的克隆附加到主体来确定元素的 offsetWidth,当它具有仅适用于其当前范围的样式时,我会得到错误的宽度。

例如:

//css

.module-container .my-elem{
边框:60px 纯黑;
现在

,当我尝试在 body 上下文中确定 my-elem 的宽度时,它将超出 120px。您可以克隆模块容器,但您的 JS 不必知道这些详细信息。

我还没有测试过,但基本上 Soul_Master 的解决方案似乎是唯一可以正常工作的解决方案。但不幸的是,从实现来看,它的使用成本可能很高,而且性能不佳(这里介绍的大多数解决方案也是如此。)

如果可能的话,请使用visibility:hidden代替。这仍然会渲染元素,让您可以轻松计算宽度。

The biggest issue being missed by most solutions here is that an element's width is often changed by CSS based on where it is scoped in html.

If I was to determine offsetWidth of an element by appending a clone of it to body when it has styles that only apply in its current scope I would get the wrong width.

for example:

//css

.module-container .my-elem{
border: 60px solid black;
}

now when I try to determine my-elem's width in context of body it will be out by 120px. You could clone the module container instead, but your JS shouldn't have to know these details.

I haven't tested it but essentially Soul_Master's solution appears to be the only one that could work properly. But unfortunately looking at the implementation it will likely be costly to use and bad for performance (as most of the solutions presented here are as well.)

If at all possible then use visibility: hidden instead. This will still render the element, allowing you to calculate width without all the fuss.

瘫痪情歌 2024-08-12 22:02:16

除了 蒂姆·班克斯发布的答案(随后解决了我的问题)之外,我还必须编辑一件简单的事情。

其他人可能也有同样的问题;我正在下拉菜单中使用 Bootstrap 下拉菜单。但此时文本可以比当前内容更宽(并且没有太多好的方法可以通过 css 解决这个问题)。

我使用:

$table.css({ position: "absolute", visibility: "hidden", display: "table" });

相反,它将容器设置为一个表,如果内容更宽,该表总是按宽度缩放。

In addition to the answer posted by Tim Banks, which followed to solving my issue I had to edit one simple thing.

Someone else might have the same issue; I'm working with a Bootstrap dropdown in a dropdown. But the text can be wider as the current content at this point (and there aren't many good ways to resolve that through css).

I used:

$table.css({ position: "absolute", visibility: "hidden", display: "table" });

instead, which sets the container to a table which always scales in width if the contents are wider.

予囚 2024-08-12 22:02:16
jQuery(".megamenu li.level0 .dropdown-container .sub-column ul .level1").on("mouseover", function () {
    var sum = 0;
    jQuery(this).find('ul li.level2').each(function(){
    sum -= jQuery(this).height();
    jQuery(this).parent('ul').css('margin-top', sum / 1.8);
    console.log(sum);
    });
});

悬停时我们可以计算列表项的高度。

jQuery(".megamenu li.level0 .dropdown-container .sub-column ul .level1").on("mouseover", function () {
    var sum = 0;
    jQuery(this).find('ul li.level2').each(function(){
    sum -= jQuery(this).height();
    jQuery(this).parent('ul').css('margin-top', sum / 1.8);
    console.log(sum);
    });
});

On hover we can calculate the list item height.

随梦而飞# 2024-08-12 22:02:16

正如之前所说,克隆并附加到其他地方的方法不能保证相同的结果,因为样式可能不同。

下面是我的方法。它沿着父级查找负责隐藏的父级,然后暂时取消隐藏以计算所需的宽度、高度等。

    var width = parseInt($image.width(), 10);
    var height = parseInt($image.height(), 10);

    if (width === 0) {

        if ($image.css("display") === "none") {

            $image.css("display", "block");
            width = parseInt($image.width(), 10);
            height = parseInt($image.height(), 10);
            $image.css("display", "none");
        }
        else {

            $image.parents().each(function () {

                var $parent = $(this);
                if ($parent.css("display") === "none") {

                    $parent.css("display", "block");
                    width = parseInt($image.width(), 10);
                    height = parseInt($image.height(), 10);
                    $parent.css("display", "none");
                }
            });
        }
    }

As has been said before, the clone and attach elsewhere method does not guarantee the same results as styling may be different.

Below is my approach. It travels up the parents looking for the parent responsible for the hiding, then temporarily unhides it to calculate the required width, height, etc.

    var width = parseInt($image.width(), 10);
    var height = parseInt($image.height(), 10);

    if (width === 0) {

        if ($image.css("display") === "none") {

            $image.css("display", "block");
            width = parseInt($image.width(), 10);
            height = parseInt($image.height(), 10);
            $image.css("display", "none");
        }
        else {

            $image.parents().each(function () {

                var $parent = $(this);
                if ($parent.css("display") === "none") {

                    $parent.css("display", "block");
                    width = parseInt($image.width(), 10);
                    height = parseInt($image.height(), 10);
                    $parent.css("display", "none");
                }
            });
        }
    }

ゃ人海孤独症 2024-08-12 22:02:15

这是我用过的一个技巧。它涉及添加一些 CSS 属性以使 jQuery 认为该元素是可见的,但实际上它仍然是隐藏的。

var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });

这有点像黑客,但似乎对我来说效果很好。

更新

我已经写了涵盖此主题的博客文章。上面使用的方法可能会出现问题,因为您将 CSS 属性重置为空值。如果他们以前有价值观怎么办?更新后的解决方案使用 jQuery 源代码中的 swap() 方法。

参考博客文章中的代码:

//Optional parameter includeMargin is used when calculating outer dimensions  
(function ($) {
$.fn.getHiddenDimensions = function (includeMargin) {
    var $item = this,
    props = { position: 'absolute', visibility: 'hidden', display: 'block' },
    dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
    $hiddenParents = $item.parents().andSelf().not(':visible'),
    includeMargin = (includeMargin == null) ? false : includeMargin;

    var oldProps = [];
    $hiddenParents.each(function () {
        var old = {};

        for (var name in props) {
            old[name] = this.style[name];
            this.style[name] = props[name];
        }

        oldProps.push(old);
    });

    dim.width = $item.width();
    dim.outerWidth = $item.outerWidth(includeMargin);
    dim.innerWidth = $item.innerWidth();
    dim.height = $item.height();
    dim.innerHeight = $item.innerHeight();
    dim.outerHeight = $item.outerHeight(includeMargin);

    $hiddenParents.each(function (i) {
        var old = oldProps[i];
        for (var name in props) {
            this.style[name] = old[name];
        }
    });

    return dim;
}
}(jQuery));

Here is a trick I have used. It involves adding some CSS properties to make jQuery think the element is visible, but in fact it is still hidden.

var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });

It is kind of a hack, but it seems to work fine for me.

UPDATE

I have since written a blog post that covers this topic. The method used above has the potential to be problematic since you are resetting the CSS properties to empty values. What if they had values previously? The updated solution uses the swap() method that was found in the jQuery source code.

Code from referenced blog post:

//Optional parameter includeMargin is used when calculating outer dimensions  
(function ($) {
$.fn.getHiddenDimensions = function (includeMargin) {
    var $item = this,
    props = { position: 'absolute', visibility: 'hidden', display: 'block' },
    dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
    $hiddenParents = $item.parents().andSelf().not(':visible'),
    includeMargin = (includeMargin == null) ? false : includeMargin;

    var oldProps = [];
    $hiddenParents.each(function () {
        var old = {};

        for (var name in props) {
            old[name] = this.style[name];
            this.style[name] = props[name];
        }

        oldProps.push(old);
    });

    dim.width = $item.width();
    dim.outerWidth = $item.outerWidth(includeMargin);
    dim.innerWidth = $item.innerWidth();
    dim.height = $item.height();
    dim.innerHeight = $item.innerHeight();
    dim.outerHeight = $item.outerHeight(includeMargin);

    $hiddenParents.each(function (i) {
        var old = oldProps[i];
        for (var name in props) {
            this.style[name] = old[name];
        }
    });

    return dim;
}
}(jQuery));
寄与心 2024-08-12 22:02:15
function realWidth(obj){
    var clone = obj.clone();
    clone.css("visibility","hidden");
    $('body').append(clone);
    var width = clone.outerWidth();
    clone.remove();
    return width;
}
realWidth($("#parent").find("table:first"));
function realWidth(obj){
    var clone = obj.clone();
    clone.css("visibility","hidden");
    $('body').append(clone);
    var width = clone.outerWidth();
    clone.remove();
    return width;
}
realWidth($("#parent").find("table:first"));
小帐篷 2024-08-12 22:02:15

根据罗伯茨的回答,这是我的功能。
如果元素或其父元素已通过 jQuery 淡出,这对我有用,可以获取内部或外部尺寸,还可以返回偏移值。

/edit1:重写函数。它现在更小,可以直接在对象

/edit2 上调用:该函数现在将在原始元素而不是主体之后插入克隆,从而使克隆可以保持继承的尺寸。

$.fn.getRealDimensions = function (outer) {
    var $this = $(this);
    if ($this.length == 0) {
        return false;
    }
    var $clone = $this.clone()
        .show()
        .css('visibility','hidden')
        .insertAfter($this);        
    var result = {
        width:      (outer) ? $clone.outerWidth() : $clone.innerWidth(), 
        height:     (outer) ? $clone.outerHeight() : $clone.innerHeight(), 
        offsetTop:  $clone.offset().top, 
        offsetLeft: $clone.offset().left
    };
    $clone.remove();
    return result;
}

var dimensions = $('.hidden').getRealDimensions();

Based on Roberts answer, here is my function.
This works for me if the element or its parent have been faded out via jQuery, can either get inner or outer dimensions and also returns the offset values.

/edit1: rewrote the function. it's now smaller and can be called directly on the object

/edit2: the function will now insert the clone just after the original element instead of the body, making it possible for the clone to maintain inherited dimensions.

$.fn.getRealDimensions = function (outer) {
    var $this = $(this);
    if ($this.length == 0) {
        return false;
    }
    var $clone = $this.clone()
        .show()
        .css('visibility','hidden')
        .insertAfter($this);        
    var result = {
        width:      (outer) ? $clone.outerWidth() : $clone.innerWidth(), 
        height:     (outer) ? $clone.outerHeight() : $clone.innerHeight(), 
        offsetTop:  $clone.offset().top, 
        offsetLeft: $clone.offset().left
    };
    $clone.remove();
    return result;
}

var dimensions = $('.hidden').getRealDimensions();
泛泛之交 2024-08-12 22:02:15

感谢您发布上面的 realWidth 函数,它真的对我很有帮助。
基于上面的“realWidth”函数,我写了一个CSS重置(原因如下所述)。

function getUnvisibleDimensions(obj) {
    if ($(obj).length == 0) {
        return false;
    }

    var clone = obj.clone();
    clone.css({
        visibility:'hidden',
        width : '',
        height: '',
        maxWidth : '',
        maxHeight: ''
    });
    $('body').append(clone);
    var width = clone.outerWidth(),
        height = clone.outerHeight();
    clone.remove();
    return {w:width, h:height};
}

“realWidth”获取现有标签的宽度。我用一些图像标签对此进行了测试。问题是,当图像给出了每个宽度(或最大宽度)的 CSS 尺寸时,您将永远无法获得该图像的真实尺寸。也许,img 具有“max-width:100%”,“realWidth”函数克隆它并将其附加到正文。
如果图像的原始尺寸大于身体,那么您得到的是身体的尺寸,而不是该图像的实际尺寸。

Thank you for posting the realWidth function above, it really helped me.
Based on "realWidth" function above, I wrote, a CSS reset, (reason described below).

function getUnvisibleDimensions(obj) {
    if ($(obj).length == 0) {
        return false;
    }

    var clone = obj.clone();
    clone.css({
        visibility:'hidden',
        width : '',
        height: '',
        maxWidth : '',
        maxHeight: ''
    });
    $('body').append(clone);
    var width = clone.outerWidth(),
        height = clone.outerHeight();
    clone.remove();
    return {w:width, h:height};
}

"realWidth" gets the width of an existing tag. I tested this with some image tags. The problem was, when the image has given CSS dimension per width (or max-width), you will never get the real dimension of that image. Perhaps, the img has "max-width: 100%", the "realWidth" function clone it and append it to the body.
If the original size of the image is bigger than the body, then you get the size of the body and not the real size of that image.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文