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

Viewed 86973

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.

14 Answers

In the JS please use 'scrollHeight'

Example Code

Assume that this div is hidden in DOM

<div class="test-div">
 //Some contents 
<div>

Javascript to find this div height

const testHeight = document.querySelector('.test-div');

testHeight.scrollHeight

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;
var timeout;

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
    clearTimeout(timeout);
    var openTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 'unset';
      clearTimeout(openTimeout);
    }, 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
    clearTimeout(timeout);
    var closeTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 0;
      clearTimeout(closeTimeout);
    }, 1);
  }
}
#example {
  overflow: hidden;
  max-height: 0;
  transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
  <textarea>Resize me</textarea>
</div>

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.

Did you try this ?

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