112

当元素不可见时,似乎在 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,因为它不可见(这是我的猜测,因为它在可见时给了我一个数字)。有没有办法在不使父级可见的情况下获得表格的宽度?

4

12 回答 12

99

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

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

这是一种 hack,但对我来说似乎工作正常。

更新

从那以后,我写了一篇涵盖该主题的博客文章。上面使用的方法可能会出现问题,因为您将 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));
于 2009-09-24T15:19:15.840 回答
41
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"));
于 2012-07-03T16:06:17.650 回答
8

根据罗伯茨的回答,这是我的功能。如果元素或其父元素已通过 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();
于 2012-12-10T06:21:07.413 回答
3

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

弹性盒示例 在此处输入图像描述

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

遗憾的是,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

于 2013-10-20T12:05:38.043 回答
3

感谢您发布上面的 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”函数克隆它并将其附加到正文。如果图像的原始尺寸大于主体,那么您将获得主体的尺寸,而不是该图像的实际尺寸。

于 2012-08-24T17:30:15.557 回答
3

如果您需要隐藏的东西的宽度并且由于某种原因无法取消隐藏,您可以克隆它,更改 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();
于 2016-10-05T20:52:14.340 回答
2

在取宽度之前使父显示显示,然后取宽度,最后使父显示隐藏。就像跟随

$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
 $('#parent').hide();
if (tableWidth > $('#parent').width())
{
    $('#parent').width() = tableWidth;
}
于 2014-04-24T12:41:21.793 回答
2

一种解决方案,虽然它不会在所有情况下都有效,但通过将不透明度设置为 0 来隐藏元素。完全透明的元素将具有宽度。

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

例如:

$(img).css("opacity", 0)  //element cannot be seen
width = $(img).width()    //but has width
于 2015-11-12T19:40:29.757 回答
1

大多数解决方案在这里遗漏的最大问题是元素的宽度通常由 CSS 根据它在 html 中的作用域进行更改。

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

例如:

//css

.module-container .my-elem{ 边框:60px 纯黑色;}

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

我尚未对其进行测试,但本质上 Soul_Master 的解决方案似乎是唯一可以正常工作的解决方案。但不幸的是,从实现来看,它的使用成本可能很高并且对性能不利(因为这里介绍的大多数解决方案也是如此。)

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

于 2014-06-04T01:41:24.037 回答
0

除了Tim Banks 发布的答案之外,在解决我的问题之后,我还必须编辑一件简单的事情。

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

我用了:

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

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

于 2013-05-16T08:29:53.793 回答
0

如前所述,clone and attach else 方法并不能保证相同的结果,因为样式可能不同。

下面是我的方法。它向上移动父母寻找负责隐藏的父母,然后暂时取消隐藏以计算所需的宽度、高度等。

    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");
                }
            });
        }
    }

于 2019-05-20T15:40:49.263 回答
0
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);
    });
});

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

于 2018-07-10T11:48:26.073 回答