views:

817

answers:

3

I've got a script executing on $(document).ready() that's supposed to vertically align block element in my layout. 90% of the time, it works without issue. However, for that extra 10% one of two things happens:

  • There's an obvious lag in the time it takes to do the centering, and the block elements jump into position. This could simply be performance related - as the page size is often large and there is a fair amount of javascript that is executing at once.

  • The centering will completely mess up, and the block element will either pushed down too far or not far enough. It appears as if it tried to calculate the height, but was getting improper measurements.

Is there any reason why executing a script on DOM-ready would not have all the correct CSS values injected into the DOM yet? (all CSS is in the <head> via a <link>).

Also, here's the script that's causing the issue (yes, it's been taken straight from here):

 (function ($) {
    // VERTICALLY ALIGN FUNCTION
    $.fn.vAlign = function() {
      return this.each(function(i) {
        var ah = $(this).height();
        var ph = $(this).parent().height();
        var mh = (ph - ah) / 2;
        $(this).css('margin-top', mh);
      });
    };
  })(jQuery);

Thanks.

+4  A: 

The DOM ready fires when all the DOM nodes are available. It has nothing to do with CSS. Try positioning the style before or try loading it differently.

Philipe Fatio
+3  A: 

To the best of my knowledge the ready event is fired when the DOM is loaded - which means that all the blocking requests (i.e. JS) have loaded and the DOM tree is completely graphed. The ready state in IE relies on a slower event trigger (document.readyState change vs DOMContentLoaded) than most other browsers so the timing is browser dependant also.

The existence of non-blocking requests (such as CSS and images) is completely asynchronous and unrelated to the ready state. If you are in a position where you require such resources you need to depend on the good old onload event.

annakata
feel free to explain the downvote anyone...
annakata
While doing some testing today I learned that somehow downloading CSS can be blocking (for executing some next `<script>` tags, not for firing the `ready` function itself). But if that was the reason to downvote, then I'd also have loved to see some explanation. Would have saved me from doing some testing...
Arjan
strager
+23  A: 
Arjan
Cuzillion (http://stevesouders.com/cuzillion/) should help you understand how different types of objects are loaded in different browsers.
strager
+1 for depth. Respect.
annakata
...but it's still **not the definitive answer**. Maybe it even matters if things are in `<head>` or `<body>`? And given the *Stylesheets Block Downloads in Firefox and JavaScript Execution in IE* (so, what about other browsers?) and *IE8 Parallel Script Loading* I guess many problems can arise for this vertical aligning script. And by the way: the waterfall for the latter in IE8 at http://www.webpagetest.org/result/090825_24AP/ does NOT show the parallel loading, and looks like IE7 at http://www.webpagetest.org/result/090825_24AQ/
Arjan
Great answer. Thank you.
Bryan M.
@Bryan, I think your question, and especially that *IE8 Parallel Script Loading*, will make me sleep worse the coming weeks... ;-) As for your question: see the following JS Bin for a version with your vAlign function (slightly altered to allow for using the provided CSS), which indeed shows that `$(this).height();` may yield zero when the CSS is loaded *after* the JavaScript, but seems fine when loaded *before* that. But still, not knowing the *why*, I'm afraid each browser may behave differently: http://jsbin.com/ofola/edit
Arjan