Skip to main content

Is $(document).ready() also CSS ready?



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.



Source: Tips4all

Comments

  1. From the 1.3 release notes:


    The ready() method no longer tries to make any guarantees about waiting for all stylesheets to be loaded. Instead all CSS files should be included before the scripts on the page. More Information


    From the ready(fn) documentation:


    Note: Please make sure that all stylesheets are included before your scripts (especially those that call the ready function). Doing so will make sure that all element properties are correctly defined before jQuery code begins executing. Failure to do this will cause sporadic problems, especially on WebKit-based browsers such as Safari.


    Note that the above is not even about actually rendering the CSS, so you may still see the screen change when ready() kicks in. But it should save you from problems.

    Actually, I find it a bit strange that just putting the CSS above the JS will solve all issues. The CSS is loaded asynchronously, so JS loading can start and finish while the CSS is still being downloaded. So if the above is a solution, then executing any JS code is then halted until all earlier requests have completed?

    I did some testing, and indeed, sometimes JS is delayed until the CSS is loaded. I don't know why, because the waterfall shows that the JS has completed loading long before downloading the CSS has finished.

    See JS Bin for some HTML and its results (this has a 10 second delay), and see webpagetest.org for its waterfall results. This uses some script from Steve Souders' cuzillion.com to mimic slow responses. In the waterfall, the reference to resource.cgi is the CSS. So, in Internet Explorer, the first external JS starts to load right after the CSS was requested (but that CSS will take another 10 seconds to finish). But the second <script> tag is not executed until the CSS has finished loading as well:

    <link rel="stylesheet" type="text/css" href=".../a script that delays.cgi" />

    <script type="text/javascript" src=".../jquery.min.js"></script>

    <script type="text/javascript">
    alert("start after the CSS has fully loaded");
    $(document).ready(function() {
    $("p").addClass("sleepcgi");
    alert("ready");
    });
    </script>




    Another test with a second external JS after getting jQuery, shows that the download of the second JS is not started until the CSS has loaded. Here, the first reference to resource.cgi is the CSS, the second the JS:



    Moving the stylesheet below all JS indeed shows that the JS (including the ready function) runs much earlier, but even then the jQuery-applied class --which is yet unknown when the JS runs-- is used correctly in my quick tests in Safari and Firefox. But it makes sense that things like $(this).height() will yield wrong values at that time.

    However, additional testing shows that it is not a generic rule that JS is halted until earlier defined CSS is loaded. There seems to be some combination with using external JS and CSS. I don't know how this works.

    Last notes: as JS Bin includes Google Analytics in each script when running from the bare URL (like jsbin.com/aqeno, the test results are actually changed by JS Bin... It seems that the Output tab on the edit URL such as jsbin.com/aqeno/edit does not include the additional Google Analytics things, and surely yields different results, but that URL is hard to test using webpagetest.org. The reference to Stylesheets Block Downloads in Firefox and JavaScript Execution in IE as given by strager is a good start for a better understanding, but I got many questions left... Also note Steve Souders' IE8 Parallel Script Loading to make things even more complicated. (The waterfalls above are created using IE7.)

    Maybe one should simply believe the release notes and documentation...

    ReplyDelete
  2. 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.

    ReplyDelete
  3. 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.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex