Find the "potential" width of a hidden element
The width of an element that has CSS visibility: hidden
is measurable. It's only when it's display: none
that it's not rendered at all. So if it's certain the elements are going to be absolutely-positioned (so they don't cause a layout change when displayed), simply use css('visibility', 'hidden')
to hide your element instead of hide()
and you should be OK measuring the width.
Otherwise, yes, show-measure-hide does work.
You can use the following function to get the outer width of an element that is inside a hidden container.
$.fn.getHiddenOffsetWidth = function () {
// save a reference to a cloned element that can be measured
var $hiddenElement = $(this).clone().appendTo('body');
// calculate the width of the clone
var width = $hiddenElement.outerWidth();
// remove the clone from the DOM
$hiddenElement.remove();
return width;
};
You can change .outerWidth()
to .offsetWidth()
for your situation.
The function first clones the element, copying it to a place where it will be visible. It then retrieves the offset width and finally removes the clone. The following snippet illustrates a situation where this function would be perfect:
<style>
.container-inner {
display: none;
}
.measure-me {
width: 120px;
}
</style>
<div class="container-outer">
<div class="container-inner">
<div class="measure-me"></div>
</div>
</div>
Please be aware that if there is CSS applied to the element that changes the width of the element that won't be applied if it's a direct descendant of body, then this method won't work. So something like this will mean that the function doesn't work:
.container-outer .measure-me {
width: 100px;
}
You'll either need to:
- change the specificity of the CSS selector ie.
.measure-me { width: 100px; }
- change the
appendTo()
to add the clone to a place where your CSS will also be applied to the clone. Ensure that where ever you do put it, that the element will be visible:.appendTo('.container-outer')
Again, this function assumes that the element is only hidden because it's inside a hidden container. If the element itself is display:none
, you can simply add some code to make the clone visible before you retrieve it's offset width. Something like this:
$.fn.getHiddenOffsetWidth = function () {
var hiddenElement $(this)
width = 0;
// make the element measurable
hiddenElement.show();
// calculate the width of the element
width = hiddenElement.outerWidth();
// hide the element again
hiddenElement.hide();
return width;
}
This would work in a situation like this:
<style>
.measure-me {
display: none;
width: 120px;
}
</style>
<div class="container">
<div class="measure-me"></div>
</div>
Two options:
- position the element outside the viewport (ex:
left:-10000px
) - use
visibility: hidden
oropacity: 0
instead ofhide()
.
Either way will work as hiding the element but still being able to get the computed width. Be careful with Safari on thi, it's awfully fast and sometimes too fast...
The only thing I can think of is to show it (or a clone of it) to allow retrieval of the offsetWidth.
For this measurement step, just make its position absolute and its x or y value a big negative, so it will render but not be visible to the user.