找到隐藏元素的“潜在”宽度

时间:2009-12-03 16:30:05

标签: javascript jquery css

我目前正在扩展lavalamp plugin以处理下拉菜单,但我遇到了一个小问题。我需要知道隐藏元素的offsetWidth。现在显然这个问题毫无意义,而我正在寻找的是元素的offsetWidth是不是被隐藏了。

解决方案是显示它,抓住宽度,然后再次隐藏?必须有更好的方法......

10 个答案:

答案 0 :(得分:34)

我唯一能想到的是显示它(或它的一个克隆)以允许检索offsetWidth。

对于此测量步骤,只需使其位置绝对且其x或y值为负值,因此它将呈现但不会对用户可见。

答案 1 :(得分:31)

具有CSS visibility: hidden的元素的宽度是可测量的。只有在它display: none时它才会被渲染。因此,如果确定元素将被绝对定位(因此它们在显示时不会导致布局更改),只需使用css('visibility', 'hidden')隐藏元素而不是hide(),您应该没问题测量宽度。

否则,是的,show-measure-hide确实有用。

答案 2 :(得分:12)

您可以使用以下函数获取隐藏容器中元素的外部宽度

$.fn.getHiddenOffsetWidth = function () {
    // save a reference to a cloned element that can be measured
    var $hiddenElement = $(this).clone().appendTo('body');

    // calculate the width of the clone
    var width = $hiddenElement.outerWidth();

    // remove the clone from the DOM
    $hiddenElement.remove();

    return width;
};

您可以根据自己的情况将.outerWidth()更改为.offsetWidth()

该函数首先克隆元素,将其复制到可见的位置。然后它检索偏移宽度,最后删除克隆。以下代码段说明了此功能完美的情况:

<style>
    .container-inner {
        display: none;
    }

    .measure-me {
        width: 120px;
    }
</style>

<div class="container-outer">
    <div class="container-inner">
        <div class="measure-me"></div>
    </div>
</div>

请注意,如果有一个CSS应用于元素,如果它是body的直接后代,则会更改将不会应用的元素的宽度,则此方法将不起作用。所以这样的事情意味着该功能不起作用:

.container-outer .measure-me {
    width: 100px;
}

您需要:

  • 改变CSS选择器的特异性即。 .measure-me { width: 100px; }
  • 更改appendTo()以将克隆添加到CSS也将应用于克隆的位置。确保您放置它的位置,该元素将可见:.appendTo('.container-outer')

同样,此函数假定元素仅被隐藏,因为它位于隐藏容器中。如果元素本身是display:none,您只需添加一些代码即可在检索克隆的偏移宽度之前使克隆可见。像这样:

$.fn.getHiddenOffsetWidth = function () {
    var hiddenElement $(this)
        width = 0;

    // make the element measurable
    hiddenElement.show();

    // calculate the width of the element
    width = hiddenElement.outerWidth();

    // hide the element again
    hiddenElement.hide();

    return width;
}

这适用于以下情况:

<style>
    .measure-me {
        display: none;
        width: 120px;
    }
</style>

<div class="container">
    <div class="measure-me"></div>
</div>

答案 3 :(得分:2)

两个选项:

  1. 将元素放在视口外(例如:left:-10000px
  2. 使用visibility: hiddenopacity: 0代替hide()
  3. 无论哪种方式都可以隐藏元素,但仍然能够获得计算出的宽度。在这期间小心Safari,它非常快,有时太快......

答案 4 :(得分:1)

我做的是; 在隐藏该元素时,将其宽度存储在其数据集中。 如果您可以通过编程方式隐藏,它将仅适用于您。

即。

隐藏时;

var elem = $("selectorOfElement");

elem.dataset.orgWidth = elem.clientWidth;

以后获取;

var elem = $("selectorOfElement");

var originalWidthWas = elem.dataset.orgWidth;

答案 5 :(得分:1)

Actual jQuery plugin

<强>用法:

console.log('width without actual: ' + $('#hidden').width());

console.log('width with actual: ' + $('#hidden').actual('width'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script>

<div style="width: 100px; display: none;">
  <div id="hidden"></div>
</div>

答案 6 :(得分:0)

那是因为它隐藏的via显示:none;我过去所做的就是制作一个“接收器”div,我使用绝对定位将其从页面上移除。然后我将新元素加载到其中,抓取尺寸,然后在完成后将其移除 - 然后在完成后移除接收器。

你可以做的另一件事是不使用hide();但要设置可见性:隐藏;显示:;但是,这意味着将在节点附加的任何位置呈现空白区域。

答案 7 :(得分:0)

我试图找到隐藏元素的工作函数,但我意识到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

答案 8 :(得分:0)

如果您知道该元素是父元素的全宽,则另一种方法是创建一个递归方法:

es5:

var getWidth;
getWidth = function($el){
  return $el.offsetWidth || getWidth($el.parentElement);
}
var width = getWidth(document.getElementById('the-element'));

es6:

let getWidth
getWidth = ($el) => $el.offsetWidth || getWidth($el.parentElement)

const width = getWidth(document.getElementById('the-element'))

答案 9 :(得分:0)

 var $hiddenElement = $('#id_of_your_item').clone().css({ left: -10000, top: -10000, position: 'absolute', display: 'inline', visibility: 'visible' }).appendTo('body');
 var width = parseInt($hiddenElement.outerWidth());
 $hiddenElement.remove();