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

偶尔善良 提交于 2019-11-27 01:49:31

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.

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

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)

Not a privileged user

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

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!

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

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.

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.

emelendez

Try to use:

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

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.

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/

Did you try this ?

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