$(document).ready()还准备好了CSS吗?

时间:2009-08-24 20:30:22

标签: javascript jquery css

我在$(document).ready()上执行了一个脚本,该脚本应该在我的布局中垂直对齐块元素。 90%的时间,它没有问题。然而,对于额外的10%,有两件事情之一发生:

  • 进行定心所需的时间明显滞后,并且块元素跳入位置。这可能仅仅与性能有关 - 因为页面大小通常很大,并且有大量的javascript同时执行。

  • 定心将完全搞乱,并且块元素将向下推得太远或不够远。似乎它试图计算高度,但测量结果不合适。

有没有理由为什么在DOM-ready上执行脚本会没有将所有正确的CSS值注入到DOM中? (所有CSS都在<head>通过<link>)。

此外,这是造成问题的脚本(是的,它是直接从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);

感谢。

5 个答案:

答案 0 :(得分:62)

来自1.3 release notes

  

ready()方法不再尝试对等待加载所有样式表做出任何保证。相反,所有CSS文件都应该包含在页面上的脚本之前。 More Information

来自ready(fn) documentation

  

注意:请确保在脚本之前包含所有样式表(尤其是那些调用ready函数的样式表)。这样做将确保在jQuery代码开始执行之前正确定义所有元素属性。如果不这样做将导致偶发问题,尤其是在基于WebKit的浏览器(如Safari)上。

请注意,上面的内容实际上并不是真正渲染 CSS,所以当ready()启动时你仍然可以看到屏幕发生变化。但它可以帮你解决问题。

实际上,我发现将JS放在JS之上会解决所有问题有点奇怪。 CSS是异步加载的,所以JS加载可以在CSS仍在下载时启动并完成。因此,如果以上是一个解决方案,那么执行任何JS代码然后停止,直到所有先前的请求都已完成?

我做了一些测试,实际上,有时 JS被延迟,直到加载CSS。我不知道为什么,因为瀑布显示JS在下载CSS之前已经完成加载。

请参阅JS Bin了解some HTMLits results(这有10秒的延迟),并查看its waterfall results的网页test.org。这使用Steve Souders'cuzillion.com的一些脚本来模仿慢响应。在瀑布中,resource.cgi的引用是CSS。因此,在Internet Explorer中,第一个外部JS在请求CSS后立即开始加载(但CSS将需要另外10秒才能完成)。但是第二个<script>标记在CSS加载完成之前不会执行:

<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> 

Waterfall with a single external JS script

Another test在获得jQuery之后使用第二个外部JS,shows第二个JS的下载在CSS加载之前不会启动。这里,resource.cgi的第一个引用是CSS,第二个是JS:

Waterfall with two external JS scripts

将样式表移动到下面所有的JS确实表明JS(包括ready函数)运行得更早,但即使这样,jQuery应用的类 - 当时还是未知的JS运行 - 在Safari和Firefox的快速测试中正确使用。但有意义的是$(this).height()之类的东西会产生错误的值。

然而,additional testing表明在加载早期定义的CSS之前,JS不会停止通用规则。似乎有一些使用外部JS和CSS的组合。我不知道这是如何运作的。

最后的注意事项:由于JS Bin在每个脚本中都包含Google Analytics(分析),因为它来自裸网址(如jsbin.com/aqeno测试结果实际上是由JS Bin改变的 ...似乎编辑网址上的“输出”标签(例如jsbin.com/aqeno/edit)不包含其他Google Analytics内容,肯定会产生不同的结果,但使用网页test.org很难测试该网址。Stylesheets Block Downloads in Firefox and JavaScript Execution in IE的引用由strager给出的是一个更好理解的良好开端,但我还有很多问题......还要注意Steve Souders'IE8 Parallel Script Loading让事情变得更复杂。(上面的瀑布是用IE7。)

也许人们应该只是相信发行说明和文档......

答案 1 :(得分:15)

CSS / JavaScript / JQuery排序对我不起作用,但以下是:

$(window).load(function() { $('#abc')...} );

答案 2 :(得分:6)

当所有DOM节点都可用时,DOM就会触发。它与CSS无关。尝试先定位样式或尝试以不同方式加载它。

答案 3 :(得分:4)

据我所知,在加载DOM时会触发ready事件 - 这意味着已加载所有阻塞请求(即JS)并完全绘制了DOM树。 IE中的就绪状态依赖于比大多数其他浏览器更慢的事件触发器(document.readyState change vs DOMContentLoaded),因此时间也取决于浏览器。

非阻塞请求(例如CSS和图像)的存在是完全异步的,与就绪状态无关。如果您处于需要此类资源的位置,则需要依赖于旧的onload事件。

答案 4 :(得分:4)

  

根据HTML5,DOMContentLoaded是一个纯粹的DOM就绪事件,不考虑样式表。 但是,HTML5解析算法要求浏览器推迟脚本的执行,直到加载所有以前的样式表。 (DOMContentLoaded and stylesheets

molily's tests (2010)

  • IE和Firefox阻止了所有后续脚本执行,直到加载样式表
  • Webkit仅阻止了外部脚本(<script src>
  • 的后续执行
  • Opera没有阻止任何脚本的后续执行

All modern browsers now support DOMContentLoaded(2017)所以他们现在可能已经标准化了这种行为。