48 votes

Est-ce que $(document).ready() est également CSS ready ?

J'ai un script qui s'exécute sur $(document).ready() et qui est censé aligner verticalement les éléments des blocs dans ma mise en page. Dans 90 % des cas, cela fonctionne sans problème. Cependant, pour ces 10 % supplémentaires, l'une des deux choses suivantes se produit :

  • Il y a un décalage évident entre le moment où le centrage est effectué et celui où les éléments du bloc se mettent en place. Il peut s'agir d'un problème de performances, car la taille de la page est souvent importante et une grande quantité de javascript est exécutée en même temps.

  • Le centrage sera complètement raté, et l'élément de bloc sera soit poussé trop loin, soit pas assez loin. Il semble qu'il ait essayé de calculer la hauteur, mais qu'il ait obtenu des mesures incorrectes.

Y a-t-il une raison pour laquelle l'exécution d'un script sur DOM-ready n'aurait pas encore toutes les valeurs CSS correctes injectées dans le DOM ? (toutes les CSS sont dans le <head> via un <link> ).

Aussi, voici le script qui cause le problème (oui, il a été pris directement à partir de aquí ) :

 (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);

Merci.

63voto

Arjan Points 7154

De la Notes de publication de la version 1.3 :

La méthode ready() n'essaie plus de garantir l'attente du chargement de toutes les feuilles de style. Au lieu de cela, tous les fichiers CSS doivent être inclus avant les scripts de la page. Plus d'informations

De la documentation ready(fn) :

Remarque : Veuillez vous assurer que toutes les feuilles de style sont incluses avant vos scripts (notamment ceux qui appellent la fonction ready). En procédant ainsi, vous vous assurerez que toutes les propriétés des éléments sont correctement définies avant que le code jQuery ne commence à s'exécuter. Le non-respect de cette procédure entraînera des problèmes sporadiques, notamment sur les navigateurs basés sur WebKit, tels que Safari.

Notez que ce qui précède ne concerne même pas la réalité rendu le CSS, donc vous pouvez toujours voir l'écran changer quand ready() donne le coup d'envoi. Mais cela devrait vous éviter des problèmes.

En fait, je trouve un peu étrange qu'il suffise de placer le CSS au-dessus du JS pour résoudre tous les problèmes. Le CSS est chargé de manière asynchrone, de sorte que le chargement du JS peut commencer et finir pendant que le CSS est encore en cours de téléchargement. Donc, si ce qui précède est une solution, alors exécution de tout code JS est alors arrêté jusqu'à ce que toutes les demandes précédentes aient été complétées ?

J'ai fait quelques tests, et en effet, parfois JS est retardé jusqu'à ce que le CSS soit chargé. Je ne sais pas pourquoi, car le waterfall montre que le chargement du JS est terminé bien avant celui du CSS.

Voir JS Bin pour un peu de HTML y ses résultats (il y a un délai de 10 secondes), et voir webpagetest.org pour ses résultats en cascade . Il utilise des script de Steve Souders. cuzillion.com pour imiter les réponses lentes. Dans la cascade, la référence à resource.cgi est le CSS. Ainsi, dans Internet Explorer, le premier JS externe commence à se charger juste après que le CSS a été demandé (mais ce CSS mettra encore 10 secondes à se terminer). Mais le deuxième <script> n'est pas exécutée tant que le chargement du CSS n'est pas terminé :

<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

Un autre test avec un deuxième JS externe après avoir obtenu jQuery, montre que le téléchargement du second JS ne soit pas lancé tant que le CSS n'est pas chargé. Ici, la première référence à resource.cgi est le CSS, le second le JS :

Waterfall with two external JS scripts

Déplacer la feuille de style en dessous de tous les JS montre en effet que les JS (y compris les ready ) s'exécute beaucoup plus tôt, mais même dans ce cas, la classe appliquée par jQuery -- qui est encore inconnue lorsque le JS s'exécute -- est utilisée correctement dans mes tests rapides dans Safari et Firefox. Mais il est logique que des choses comme $(this).height() donnera des valeurs erronées à ce moment-là.

Cependant, test supplémentaire montre que il ne s'agit pas d'une règle générique selon laquelle le JS est arrêté jusqu'à ce que le CSS défini précédemment soit chargé. . Il semble y avoir une combinaison avec l'utilisation de JS et CSS externes. Je ne sais pas comment cela fonctionne.

Dernières remarques : comme JS Bin inclut Google Analytics dans chaque script lorsqu'il est exécuté à partir de l'URL nue (par exemple jsbin.com/aqeno , les résultats du test sont réellement modifiés par JS Bin ... Il semble que l'onglet Sortie de l'URL d'édition tel que jsbin.com/aqeno/edit n'inclut pas les éléments supplémentaires de Google Analytics, et donne sûrement des résultats différents, mais cette URL est difficile à tester avec webpagetest.org. La référence à Les feuilles de style bloquent les téléchargements dans Firefox et l'exécution de JavaScript dans IE comme indiqué par strager est un bon début pour une meilleure compréhension, mais il me reste beaucoup de questions... Notez également que Steve Souders Chargement du script parallèle d'IE8 pour rendre les choses encore plus compliquées. (Les cascades ci-dessus sont créées en utilisant IE7).

Peut-être faut-il simplement croire les notes de version et la documentation...

15voto

Martin Dvorak Points 96

L'ordre CSS/JavaScript/JQuery ne fonctionne pas pour moi, mais ce qui suit fonctionne :

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

6voto

Philipe Points 1838

Le DOM ready se déclenche lorsque tous les nœuds du DOM sont disponibles. Cela n'a rien à voir avec le CSS. Essayez de positionner le style avant ou essayez de le charger différemment.

4voto

annakata Points 42676

A ma connaissance, l'événement ready est déclenché lorsque le DOM est chargé - ce qui signifie que toutes les requêtes bloquantes (i.e. JS) ont été chargées et que l'arbre DOM est complètement gravé. L'état prêt dans IE repose sur un déclencheur d'événement plus lent (document.readyState change vs DOMContentLoaded) que la plupart des autres navigateurs, de sorte que le timing dépend également du navigateur.

L'existence de requêtes non bloquantes (comme les CSS et les images) est totalement asynchrone et sans rapport avec l'état prêt. Si vous êtes dans une position où vous avez besoin de telles ressources, vous devez dépendre du bon vieil événement onload.

4voto

sam Points 1960

Selon le HTML5, DOMContentLoaded est un événement DOM ready sans tenir compte des feuilles de style. Cependant l'algorithme d'analyse du HTML5 exige que les navigateurs reportent l'exécution des scripts jusqu'à ce que toutes les feuilles de style précédentes soient chargées. ( DOMContentLoaded et feuilles de style )

En les tests de molily (2010) ,

  • IE et Firefox ont bloqué toute exécution ultérieure de script jusqu'à ce que les feuilles de style soient chargées.
  • Webkit a bloqué l'exécution ultérieure uniquement pour les scripts externes ( <script src> )
  • Opera n'a pas bloqué l'exécution ultérieure d'un scripts.

Tous les navigateurs modernes supportent maintenant DOMContentLoaded (2017), il est donc possible qu'ils aient normalisé ce comportement à l'heure actuelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X