I have a web page that is injecting HTML delivered via AJAX. I don't know, a priori, the size of the content, but I need to position the content on the page based on its size. Here's a simple approach that doesn't work:
- Set parent container's opacity to 0.
- Insert the content into the DOM.
- Measure the sizes, e.g.
$el.outerWidth(true)
. - Position the content based on those sizes.
- Set the parent container's opacity (back) to 1.0.
The problem with this approach is that the content is quite complex and includes images. When outerWidth()
is called, the browser hasn't yet finished repainting the screen so that the sizes returned aren't accurate. (Interestingly, in my case the initial dimensions are always significantly larger than the ultimate values, not 0 as I might expect.)
I can reduce the problem by setting a timer between steps 2 and 3, but no matter how long I make the timer, there will surely be some browser on some system that will exceed it. And if I make the timer long enough to cover most cases, that will penalize users with faster systems by introducing unnecessary delays. Although a few of the answers referenced below suggest a setTimeout(fn, 0)
is sufficient, I've found that not to be be the case. I've measured paint times as high as 60 ms on a 2012 MacBook Air, and one answer below suggests 500 ms.
It looks like Mozilla at one time had an onPaint
event that might have solved my problem … if it still existed and if other browsers had adopted it. (Neither of which is the case.) And Mutation Observers don't seem to account for paint time when reporting changes in elements.
Solutions or comments very much appreciated. As noted below, this has been asked before but most of the questions are at least a year old and I'm desperate enough to try again.
Related questions that don't, unfortunately, offer a workable answer
- How to detect when an image has finished rendering in the browser (i.e. painted)?
- jQuery - How to execute script as soon as we know true height (with images) of ajax-loaded element?
- DIV width immediately after append is calculating wrong?
- jQuery returns height of 0 for div element immediately after appending element
- Javascript: unable to get height of newly created element
- jQuery: Why does .width() sometimes return 0 after inserting elements with .html()?
Update: Well, it appears there simply isn't a general solution for this problem. In my specific case, I found a property that would reliably change once the content was loaded and layout was complete. The JavaScript polls for a change in this property. Not at all elegant, but it was the best option I could find.