I need to measure the offsetHeight of a div that is inside of a hidden element.
-
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)
-
Use z-index to hide element under non-transparent element, show it, and get height.
讨论(0)
-
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)
-
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)
-
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)
-
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)