Solution: Javascript returns incorrect width or height of an element containing image(s) when page first loads
Recently, I’ve been doing quite a lot of JavaScript development, part of which involved equalising heights of a group of similar elements on the page. I thought this would be very simple and indeed it was but it threw up a JavaScript quirk which I have seen several times before. The solution is simple, but here’s what happens and why (in this example, my browser is Firefox 3.6.8 on Mac OSX):
As I mentioned, I was attempting to use JavaScript to measure the height of a group of elements, each of which contained an image and some text and were fixed-width. The JavaScript miscalculated the height of the elements when the page first loaded and also when I cleared my browser cache then reloaded the page but a normal refresh would result in the JavaScript returning the correct height for the elements. The reason this happens is a pretty obvious once you think about it in detail.
SInce I had been lazy and had not specified the dimensions of the images on my page, I was relying on the browser to render the images at their native size. My JavaScript was being run on “domready” (an event which most JavaScript frameworks such as Mootools and JQuery add under some guise – this fires when the DOM tree has been fully constructed but before images etc have been downloaded) – this is a vital factor.
Because I didn’t specify the dimensions of the images on my page, the browser had no way of determining what those dimensions should be until the images had been downloaded and analysed (this would occur after “domready”, at “load”). Once the images on my page had been downloaded and cached, the browser knew their dimensions even at “domready” and could account for the effect the images had on the dimensions of their container elements.
So, the solution is very simple, either specify the dimensions of your images, preferably using either inline or external styles (or by oldschool HTML attributes if you need to) or run your JavaScript on “load” rather than “domready”. The former (specifying the dimensions of your images) is most likely to be the best solution since it will give faster performance for your web page(s).
I found today through a bit of testing, that Firefox 3.6 and Opera 10 behave as above i.e. they report the container element dimensions correctly after the image has been cached. I then tested Safari 5 and found that it never reports the correct dimensions of the container element if the dimensions of the image(s) are not specified – this may be due to my cache settings in Safari.
You can see an example of this behaviour here – box1 should be reported with smaller height than box 2 on first load with Firefox and Opera and probably always with Safari, if you then refresh the page, both heights should be displayed correctly. I have used Mootools element.getSize() and element.getCoordinates() in the example which are triggered onDomReady.
NOTE: I’d expect the same behaviour to occur with widths if the width of your element is dependent on the width of an image it contains.
If you find any other behaviour with other browsers, i’d be interested to know so please leave me a comment below!
I hope that saves someone the time of tracking this bug through and explains why the apparently quirky behaviour is happening.