3

Pretty simple task: using jquery I need to calculate the width of an input before the input is visible on the screen.

http://jsfiddle.net/ajbeaven/mKQx9/

Here is the code for convenience:

<div style="display:none;">
    <input />
</div> 

<script type="text/javascript">
    $(function () {
        alert($('input').width());
        $('div').show();
    });
</script>

Alert always shows 0

How do I calculate width without having to forcibly make the element visible, calculate the width, then hide them again?

ajbeaven
  • 9,265
  • 13
  • 76
  • 121

5 Answers5

5

You can't. Hidden elements, by definition, have a width of 0.

If you need to calculate dimension, you might be able to get away with "showing" it offscreen (at some odd position, like left: -9999px; top: -9999px.

Also, this appears to be a duplicate of: jQuery - Get Width of Element when Not Visible (Display: None)

Community
  • 1
  • 1
OverZealous
  • 39,252
  • 15
  • 98
  • 100
4

You have to "forcibly make the element visible, calculate the width, then hide it again" There isn't another option. If it weren't for your blocking call to alert the browser wouldn't render the change during the time element is showing. You can fix it by showing it, grabbing the width, and hiding it again before the alert like:

$('div').show();
var w = $('input').width();
$('div').hide();

alert(w);
$('div').show();

EDIT In response to comment below. You should test this across different browsers (It at least works in the latest stale release of Google Chrome)

var w;
(function(){
    var thediv = $('input').get(0);
    var $copy = $(thediv);
    if(window.getComputedStyle)
            $copy.get(0).style = window.getComputedStyle(thediv,null);
    else if(thediv.currentStyle)
            $copy.get(0).style = thediv.currentStyle;
    w = $copy.width();
})();

alert(w);
$('div').show();
Paul
  • 139,544
  • 27
  • 275
  • 264
  • hmm, sad. Unfortunately the reality is not so simple as the inputs are deep in a tree where many of it's parents can also be `display:none;`. Thanks anyway! – ajbeaven Aug 02 '11 at 06:53
  • @ajbeaven Hi, I updated my solution. It might require some tweaking to make it cross-browser, but I think it's fairly robust as is. – Paul Aug 05 '11 at 03:50
  • @ajbeaven, Thanks. I think I might fiddle with it and make sure it's cross browser and then make some blog post with it or something. I've seen a lot of more complicated solutions for this and a lot of people trying to do it, so it could help some other people, right? – Paul Aug 05 '11 at 04:56
  • @Paulpro I agree it is a good idea, unfortunately it does not work (or I cannot manage it to work) on Chrome 44.0.2403.155 – yodabar Aug 22 '15 at 22:39
2

You can change from display: none to visibility: hidden and it will give a non-zero width, but as you know it takes up space on the output and may not be what you want.

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
1

I found a solution which I think adds to what is on SO regarding this 'problem'.

(function ($) {
    $.fn.getHiddenDimensions = function (includeMargin) {
        var $item = this,
        props = { position: 'absolute', visibility: 'hidden', display: 'block' },
        dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
        $hiddenParents = $item.parents().andSelf().not(':visible'),
        includeMargin = (includeMargin == null) ? false : includeMargin;

        var oldProps = [];
        $hiddenParents.each(function () {
            var old = {};

            for (var name in props) {
                old[name] = this.style[name];
                this.style[name] = props[name];
            }

            oldProps.push(old);
        });

        dim.width = $item.width();
        dim.outerWidth = $item.outerWidth(includeMargin);
        dim.innerWidth = $item.innerWidth();
        dim.height = $item.height();
        dim.innerHeight = $item.innerHeight();
        dim.outerHeight = $item.outerHeight(includeMargin);

        $hiddenParents.each(function (i) {
            var old = oldProps[i];
            for (var name in props) {
                this.style[name] = old[name];
            }
        });

        return dim;
    }
} (jQuery));

Source: http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/

ajbeaven
  • 9,265
  • 13
  • 76
  • 121
0

try this:

<div id="test" style="display:none;">
  <input type="text"/>
</div> 

<script type="text/javascript">
  $(function () {
    $('#test').css({ position: "absolute", visibility: "hidden", display: "block" });
    var width = $('#test').width();
    $('#test').css({ position: "", visibility: "", display: "none" });
  });
</script>
Calvin
  • 1,305
  • 8
  • 17