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

前端 未结 13 1550
萌比男神i
萌比男神i 2020-11-27 06:00

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

相关标签:
13条回答
  • 2020-11-27 06:43

    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.

    0 讨论(0)
  • 2020-11-27 06:44

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

    0 讨论(0)
  • 2020-11-27 06:46

    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)

    0 讨论(0)
  • 2020-11-27 06:50

    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.

    0 讨论(0)
  • 2020-11-27 06:51

    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>

    0 讨论(0)
  • 2020-11-27 06:53

    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).

    0 讨论(0)
提交回复
热议问题