Need to find height of hidden div on page (set to display:none)

六月ゝ 毕业季﹏ 提交于 2019-11-26 09:46:23

问题


I need to measure the offsetHeight of a div that is inside of a hidden element.

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

The parent div must be set to \"display:none\". I have no control over that. I realize that the offsetHeight of the child div is going to be 0. I need to find a workaround.

Something I\'ve toyed with is when the page loads, I copy the childnodes of parent, inject in a div on the page that is set to \"visiblity:hidden\". Then I measure the height of those elements, and remove the nodes when done.

Any other thoughts?

Update: What I wound up having to do was this:

Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that\'s one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it\'s parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.

Once all elements are measured I reset all of the elements back to display:none.


回答1:


You need to make element's parent visible for that one very short moment while you're getting element's dimensions. In a generic solution, all ancestors are usually traversed and are made visible. Then their display values are set back to original ones.

There are performance concerns of course.

We considered this approach in Prototype.js implementation but ended up with getWidth and getHeight making only actual element visible, without traversing ancestors.

The problem with alternative solutions - such as taking element out of "hidden" parent - is that certain styles might no longer apply to an element once it's out of its "regular" hierarchy. If you have a structure like this:

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

and these rules:

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

then taking element out of its parent will actually result in wrong dimensions.




回答2:


You could clone the element, absolutely position it at -10000,-10000, measure the clone and destroy it.




回答3:


If you use style.display = "none", the element will have 0 width and height,
but using the style.visibility = "hidden" instead, the element will have the width and height calculated by the browser (as normally).




回答4:


Made a pure js solution with no Jquery and with no cloning (which I guess is faster)

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

here is the demo https://jsfiddle.net/xuumzf9k/1/

Please let me know if you can find any improvements to this (as I use this in my main projects)




回答5:


So here's working jQuery solution based on lod3n's answer and with help of 999's comment:

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

Enjoy!




回答6:


A workaround is to set the height to 0

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

Then to get the elements scrollHeight.

document.querySelector('.hidden').scrollHeight

The scrollHeight will correctly give you the height though the element does not appear. I don't think it affects element flow either.

Example: https://jsfiddle.net/de3vk8p4/7/
Reference: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements#How_big_is_the_content.3F




回答7:


Use z-index to hide element under non-transparent element, show it, and get height.




回答8:


Until the element is rendered, it has no height. Even if you clone the parent object and display it somewhere that can't be seen by the user, there's not guarantee that the clone will have the same height as the final size of the hidden object.

There are many things that can affect the height that wouldn't necessarily be rendered in the clone - anything in the DOM and its interaction with the CSS rules could cause a change in rendering any other element of the DOM. Short of cloning the entire document (and even that's not fool-proof) you have no way of determining the height of the hidden object.

If you must know the height before it's displayed to the user, you'll have to "hack" it by displaying it for as short of a time as possible then hiding it again. Most likely, the user will see this hiccup and not be pleased by the result.




回答9:


So, you cannot even change the display:none; to height:0; overflow:hidden; ? Maybe you could override that in your own stylesheet like so:

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

And then as you are using YUI (assuming YUI 2) you could use this:

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

To get the dimensions and offset of the child.




回答10:


Try to use:

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



回答11:


What I wound up having to do was this:

Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that's one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it's parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.

Once all elements are measured I reset all of the elements back to display:none.




回答12:


A helper function ---

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

Creates a clone, appends it to the DOM (hidden), takes the height, then removes it.

Position of fixed and the top/left are in case your app allows scrolling at the body-level - it attempts to prevent a scrollbar rave party - can remove if you handle scrolling in children elements.

Overflow, height, and max-height settings to attempt to 'reset' height settings and let it be it's natural height on the clone.

Visibility for the obvious and pointer-events as a 'just in case' the rendering of the element takes a while and don't want to interrupt user-input.

An example having an 'accordion-like' animated open/close allowing for dynamic heights.

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>



回答13:


Did you try this ?

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


来源:https://stackoverflow.com/questions/1473584/need-to-find-height-of-hidden-div-on-page-set-to-displaynone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!