Elements added to the DOM have no width or height in jQuery?

1.3k views Asked by At

I've added a block-level element to the DOM, such a p tag. Its dimensions should be automatically computed (e.g. auto). I cannot, however, retrieve its height with jQuery, at least initially. After some time has passed (presumably some layout processing has occurred), I can retrieve the height.

What has to occur in order for an element to actually be measurable, other than adding it to the DOM, in order for its computed height to be retrievable?

To be specific, I have a select element with some option elements that have image URL data attached to each of them them. I call an image-picker plugin that reads the option tag data, hides the select element, and turns the options into a container with div elements that look like this:

<div class='container' style='width:800px'>
    <div class='convertedOptionElement' style='width:33.33%'>
        <div class='thumb' style='width:100%'>
            <img src="https://lh3.ggpht.com/hhG6g0m8Q6QqZnloQJHV9uXFdsDjpzD0vJdkbra5e_PiwOjVXuBdVR0D2L0RPmwb1zw=h900">
            <p>Image Title</p>
        </div>
    </div>
</div>

So there I have a fixed-width container that will be filled with div elements at 33.33% width (producing 3 columns). Each of those div's represent one of the converted option elements. Within each of those, there's a div element at 100% width, which contains an img and p tag.

Furthermore, I'm using the imagesLoaded plugin and the masonry plugin to lay out the images. On the imagesLoaded progress event, which runs after each image is loaded, I can clearly see that the img element has a non-zero height and a width. Its containers, however, do not, nor does the p tag.

The only thing special that may be occurring is that immediatly after creating the elements with the image-picker plugin, I'm detaching them with $('.convertedOptionElement').detach(), and then in the progress event for imagesLoaded, which fires as each image is loaded, I append them to the container and call masonry.appended method so it performs the layout. That's where the problem arises, because in spite of everything being in the DOM, the computed heights are zero.

Please note that even if I provide exact widths (e.g. 250px instead of 33.33% and 100%), and then in that very same loaded event handler I explicitly set a width and height in jQuery by computing a scaled height from the existing image dimensions (i.e. all parent elements are given explicit sizes)... the paragraph tag still has a zero height.

Here is my code, but this is working. It's not working in the exact context I'm using though, and I can't figure out why. http://jsfiddle.net/p7cgahro/7/

2

There are 2 answers

2
Rory McCrossan On

Given your code:

$(document).append('<p>Hello</p>');
console.log($(document).find('p').height()); //zero, why?

You are attempting to append HTML to the document which is invalid. Use the body element instead:

$('body').append('<p>Hello</p>');
console.log($('body').find('p').height());

Working example

0
Triynko On

The problem was a parent element that had 'display:none;', which I was not expecting it to have.

It turns out that after calling bootstrap's modal('show') on a dialog, it doesn't actually change anything right away.

For example, immediately after the call to modal('show'), the dialog still has CSS class fade (without class in) and it's display style is still none. After some time, the in class is added which basically override's the fade class's zero opacity and set its to 1 (with a CSS animation). The display:none style is also removed.

Essentially, the problem boiled down to the fact that a parent element either had display:none and opacity:0, at the moment we were trying to make measurements. In particular, it was the display:none value that threw off the measurements.

Interestingly, this issue could have been answered straightforwardly in the original version of my question, without a single line of code, since I simply asked "What has to occur in order for an element to actually be measurable, other than adding it to the DOM, in order for its computed height to be retrievable?"

The answer is... none of the parent elements can have 'display:none'.