需要在页面上找到隐藏div的高度(设置为display:none)

时间:2009-09-24 19:03:54

标签: javascript html css yui

我需要测量隐藏元素内部div的offsetHeight。

<div id="parent" style="display: none;">
    <div id="child">Lorem Ipsum dolor sit amet.</div>
</div>

父div 必须设置为“display:none”。我无法控制。我意识到子div的offsetHeight将为0.我需要找到一个解决方法。

我玩过的东西是页面加载时,我复制父项的子节点,在设置为“visiblity:hidden”的页面上注入div。然后我测量这些元素的高度,并在完成后删除节点。

还有其他想法吗?

更新 我最不得不做的是:

使用YUI 2,在页面加载时,我发现给定类名的所有元素都设置为display:none,或者其高度和宽度为0(这是测量元素是否存在的一种方式,或者父元素是设置为display:none)。然后我将该元素设置为display:block。然后,我检查了它的父母同样的事情,并向父母展示,直到找到一个可见的父母。一旦最高显示:没有祖先设置为显示:阻止,我可以测量我的元素。

测量完所有元素后,我将所有元素重置为display:none。

13 个答案:

答案 0 :(得分:21)

当你获得元素的尺寸时,你需要使元素的父元素可见非常短暂。在通用解决方案中,通常遍历所有祖先并使其可见。然后他们的display值将重新设置为原始值。

当然存在性能问题。

我们在Prototype.js实现中考虑了这种方法,但结果只有getWidthgetHeight 只使实际元素可见,而没有遍历祖先。

替代解决方案的问题 - 例如将元素从“隐藏”父元素中取出 - 是某些元素一旦超出其“常规”层次结构就可能不再适用于该元素。如果你有这样的结构:

<div class="foo" style="display:none;">
  <div class="bar">...</div>
</div>

以及这些规则:

.bar { width: 10em; }
.foo .bar { width: 15em; }

然后将元素从其父元素中取出实际上会导致错误的维度。

答案 1 :(得分:15)

你可以克隆元素,绝对定位在-10000,-10000,测量克隆并销毁它。

答案 2 :(得分:11)

制作一个没有Jquery且没有克隆的纯js解决方案(我猜想更快)

var getHeight = function(el) {
    var el_style      = window.getComputedStyle(el),
        el_display    = el_style.display,
        el_position   = el_style.position,
        el_visibility = el_style.visibility,
        el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),

        wanted_height = 0;

    // if its not hidden we just return normal height
    if(el_display !== 'none' && el_max_height !== '0') {
        return el.offsetHeight;
    }

    // the element is hidden so:
    // making the el block so we can meassure its height but still be hidden
    el.style.position   = 'absolute';
    el.style.visibility = 'hidden';
    el.style.display    = 'block';

    wanted_height     = el.offsetHeight;

    // reverting to the original values
    el.style.display    = el_display;
    el.style.position   = el_position;
    el.style.visibility = el_visibility;

    return wanted_height;
}

这是演示 https://jsfiddle.net/xuumzf9k/1/

如果你能找到任何改进(我在我的主要项目中使用它),请告诉我。

答案 3 :(得分:10)

如果使用style.display = "none",则元素的宽度和高度为0,
但是使用style.visibility = "hidden"代替,元素将具有浏览器计算的宽度和高度(通常)。

答案 4 :(得分:4)

所以这里是基于lod3n的答案并在999评论的帮助下运行jQuery解决方案:

var getHiddenElementHeight = function(element){
    var tempId = 'tmp-'+Math.floor(Math.random()*99999);//generating unique id just in case
    $(element).clone()
    .css('position','absolute')
    .css('height','auto').css('width','1000px')
    //inject right into parent element so all the css applies (yes, i know, except the :first-child and other pseudo stuff..
    .appendTo($(element).parent())
    .css('left','-10000em')
    .addClass(tempId).show()
    h = $('.'+tempId).height()
    $('.'+tempId).remove()
    return h;
}

享受!

答案 5 :(得分:1)

在渲染元素之前,它没有高度。即使您克隆父对象并将其显示在用户无法看到的某个位置,也无法保证克隆的高度与隐藏对象的最终大小相同。

有很多事情可以影响高度,而这些高度不一定会在克隆中呈现 - DOM中的任何内容及其与CSS规则的交互都可能导致渲染DOM的任何其他元素发生变化。如果没有克隆整个文档(甚至不是万无一失),你就无法确定隐藏对象的高度。

如果必须知道高度才会显示给用户,您必须通过尽可能短的时间显示它来“破解”它,然后再次隐藏它。最有可能的是,用户会看到这种打嗝而不会对结果感到满意。

答案 6 :(得分:1)

那么,您甚至无法将display:none;更改为height:0; overflow:hidden;?也许你可以在你自己的样式表中覆盖它,如下所示:

div#parent { display: block !important; height:0; overflow:hidden; }

然后当你使用YUI(假设YUI 2)时你可以使用它:

var region = YAHOO.util.Dom.getRegion('child');

获取孩子的尺寸和偏移量。

答案 7 :(得分:1)

尝试使用:

#parent{ display:block !important; visibility:hidden; position:absolute} 

答案 8 :(得分:0)

使用z-index隐藏非透明元素下的元素,显示它并获得高度。

答案 9 :(得分:0)

我最不得不做的是:

使用YUI 2,在页面加载时,我发现给定类名的所有元素都设置为display:none,或者其高度和宽度为0(这是测量元素是否存在的一种方式,或者父元素是设置为display:none)。然后我将该元素设置为display:block。然后,我检查了它的父母同样的事情,并向父母展示,直到找到一个可见的父母。一旦最高显示:没有祖先设置为显示:阻止,我可以测量我的元素。

测量完所有元素后,我将所有元素重置为display:none。

答案 10 :(得分:0)

一种解决方法是将height设置为0

.hidden { 
  height:0; 
  overflow: hidden; 
}

然后获取元素scrollHeight

document.querySelector('.hidden').scrollHeight

scrollHeight将正确显示您的高度,尽管该元素未出现。我认为它也不影响元素流。

示例:https://jsfiddle.net/de3vk8p4/7/

答案 11 :(得分:0)

辅助功能---

function getElementHeight(el) {
  var clone           = el.cloneNode(true);
  var width           = el.getBoundingClientRect().width;
  clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ' + width + 'px';
  document.body.append(clone);
  var height = clone.getBoundingClientRect().height + 'px';
  clone.remove();
  return height;
}

创建一个克隆,将其附加到DOM(隐藏),获取高度,然后将其删除。

fixedtop / left的位置是为了防止您的应用允许在主体级滚动-尝试防止滚动条狂欢派对-如果您处理,则可以删除滚动子元素。

Overflowheightmax-height设置尝试“重置”高度设置,使其成为克隆上的自然高度。

Visibility用于明显的事件和指针事件,以防万一,该元素的呈现需要一段时间,并且不想中断用户输入。

一个具有“手风琴式”动画打开/关闭的示例,允许动态高度。

function getElementHeight(el) {
  var clone = el.cloneNode(true);
  clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset';
  document.body.append(clone);
  var height = clone.getBoundingClientRect().height + 'px';
  clone.remove();
  return height;
}

var expanded = false;

function toggle() {
  var el = document.getElementById('example');
  expanded = !expanded;

  if (expanded) {
    el.style.maxHeight = getElementHeight(el);

    // Remove max-height setting to allow dynamic height after it's shown
    setTimeout(function() {
      el.style.maxHeight = 'unset';
    }, 1000); // Match transition
  } else {
    // Set max height to current height for something to animate from
    el.style.maxHeight = getElementHeight(el);

    // Let DOM element update max-height, then set to 0 for animated close
    setTimeout(function() {
      el.style.maxHeight = 0;
    }, 1);
  }
}
#example {
  overflow: hidden;
  max-height: 0;
  transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
  <textarea>Resize me</textarea>
</div>

答案 12 :(得分:-5)

你试过这个吗?

setTimeout('alert($(".Var").height());',200);