Dans la création de pages web, on lit souvent qu’il faut mettre les fichiers CSS dans head, au début du document HTML et qu’il faut mettre le JavaScript à la fin. Bien rarement par contre il est dit pourquoi.

disposition en 3D des éléments d’une page web
Schématisation en 3D des éléments d’une page web.


Lors du processus d’affichage d’une page web, la première phase consiste au téléchargement de la page web : le document HTML ainsi que les images, mais aussi les feuilles CSS de styles et les scripts JS liés.

Le contenu HTML, c’est ce qu’on voit : le texte, les images, les champs de recherche, etc.
Les styles CSS, c’est comment le HTML sera vu : disposition, couleurs polices et taille du texte, couleur du fond de la page.

Le CSS et le HTML sont donc nécessaires à l’affichage de la page web et donc au visiteur qui souhaite lire votre site.
Les scripts JS, en revanche, ce sont des instructions destinées au navigateur, pas à l’internaute. Le navigateur les traite en tâche de fond et l’utilisateur de voit pas de différence s’ils sont là où pas (normalement).

Le problème, c’est la capacité du JS de modifier le HTML et le CSS. Du coup, le navigateur qui reçoit une page HTML+CSS n’aura en réalité la totalité de la page web qu’une fois qu’il aura terminé d’exécuter les scripts JS. Avant cela, il ne peut (presque) rien faire : il va bien commencer à afficher les différents éléments de la page (menu, titres, liens…) mais si le JS supprime le menu entre temps, il devra tout recommencer.

La solution du navigateur pour le problème du JS ?

Commencer d’effectuer le rendu (l’affichage) de la page et mettre ce rendu en pause quand il détecte un script JS : à ce moment là, il doit télécharger tout le script JS et l’exécuter entièrement (ce qui a des chances de modifier le HTML et le CSS, souvenez-vous) avant de reprendre de rendu (et au besoin le recommencer, si le JS a beaucoup modifié le HTML ou le CSS).
Le fait pour le navigateur d’avoir à se mettre en pause lorsqu’il rencontre un script, nous fait dire que le JS est bloquant.

Le CSS, le HTML et même les images sont non-bloquant : le navigateur peut continuer à décoder la page web même quand il est encore en train de télécharger du CSS, par exemple. Il peut donc télécharger du CSS en parallèle avec le HTML. Une fois qu’il a tout le CSS, il commence le rendu tel qu’il est décrit par le CSS. Le décodage du HTML, lui, se poursuit durant tout ce temps.

Un document HTML simple, sans CSS ni JS, s’affiche quand même : c’est le rendu par défaut d’une page web : le fond est blanc, le texte est noir et tous les éléments sont à la suite les uns des autres. Bref, c’est moche, mais ça reste lisible.

mon site sans CSS
Mon site tel qu’il s’affiche sans les styles CSS.


Le navigateur, quand il reçoit le document HTML, commence par effectuer le rendu par défaut. Lorsqu’il reçoit le CSS, ce rendu par défaut continu (de façon à ce que la page soit lisible — même si c’est moche). Le rendu par défaut est stoppé quand tout le CSS est arrivé : à ce moment là, c’est le rendu tel qu’il est décrit dans le CSS qui est appliqué : les couleurs, les fonds, les bordures, les ombres… tout ça est alors affiché. Le traitement du CSS ne bloque pas le téléchargement du reste du contenu de la page.


Pour l’instant je n’ai pas vraiment répondu à la question « pourquoi mettre le JS à la fin et le CSS au début ? », mais j’y viens.

On sait que l’affichage des données (texte, images…) dans la page web commence dès que le HTML est en train d’être téléchargé : ceci permet à l’internaute d’accéder à l’information contenue dans la page le plus rapidement possible, même si le CSS et le JS ne sont pas encore arrivés. Une fois que tout le CSS est obtenu, l’information est alors restructurée, organisée sur la page et coloriée.
Lorsque le navigateur reçoit un script JS, l’affichage est mis en pause : le JS doit finir de s’exécuter avant que l’affichage puisse continuer.

L’intérêt de placer le CSS en haut et le JS en bas se trouve à ce niveau.

Si on met le CSS en haut, c’est pour que l’affichage « colorié » se fasse le plus vite possible : pour que la page web soit « jolie » et « organisée » tout de suite, avant que l’utilisateur ne puisse se trouver face à une page web dans son rendu par défaut. Cela tombe d’ailleurs bien : le téléchargement du CSS n’est pas bloquant : l’information dans la page web continue d’arriver pendant ce temps : l’affichage de la page web n’est pas ralentie par le CSS. C’est juste mieux de l’avoir avant, pour que l’affichage se fasse directement comme la page doit être, sans à avoir un rendu par défaut entre-temps.

Parallèlement si on met le JS en bas du document, toute l’information contenue dans la page web sera déjà affichée (car déjà téléchargée et déjà rendue à l’écran). Au moment où le navigateur rencontre le JS, l’écran ne sera pas tout vide ni tout blanc : l’internaute pourra commencer à lire la page web pendant que le navigateur traite le script JS et effectue les derniers changements.

Si on mettait le JS tout en haut, la page n’aurait encore aucune donnée que l’affichage et le téléchargement seraient déjà bloqués : l’internaute n’aurait alors qu’une simple page blanche et rien à lire. Si le script est gros, cela peur prendre plusieurs secondes. Si ça ne semble pas long dit comme ça, croyez-moi, ça l’est : si toutes les pages web mettaient 2 secondes de plus pour s’afficher, vous le verriez très rapidement. Placer le JS en haut n’est donc pas génial, car il oblige le navigateur à tout mettre en pause et l’internaute à attendre devant une page vide.
Mettre le CSS en bas de la page n’est pas avantageux non plus : le CSS n’est pas bloquant. Il peut être téléchargé en parallèle avec le reste. Si on le met en bas de la page, il sera téléchargé en dernier et tout seul, donc sans tirer profit de la possibilité de télécharger deux choses en même temps. De plus, tout le document HTML sera déjà là mais affiché avec le rendu par défaut du navigateur, donc tout moche. Si l’internaute a déjà commencé à lire, il verrait alors la page se modifier sous ses yeux à l’instant même où tout le CSS aura fini de télécharger et que le rendu se fasse.

Il convient donc naturellement de mettre le CSS le plus tôt possible dans la page (dans le head) pour tirer profit du téléchargement en parallèle du CSS avec d’autres ressources et pour que le rendu se fasse directement de façon voulue ; et il faut placer le JS en bas du document pour que quand le navigateur le trouve, tout le reste de la page soit déjà affiché à l’écran et que l’internaute puisse commencer à lire votre page pendant le traitement du script JS par le navigateur en tâche de fond.


Quelques liens :

9 commentaires

gravatar
Remb a dit :

Super, ca me rapelle un article lu il y a quelques semaines au sujet des fichiers CSS :
Pour certains gros sites on peut accélérer le chargement avec 2 fichiers CSS.
Le premier est trés léger, il charge ce qui est important dans la page de facon a avoir un premier rendu (surtout pour les éléments visibles au dessus de la 'ligne de flottaison' : le haut de la page visible lorsque l'on y arrive pour la premiere fois).
Le second, plus lourd, charge ensuite pour styliser le reste et terminer le rendu de la page.

Merci Timo pour cet article :)

gravatar
Stephanout a dit :

Salut !

Oui, voilà le truc à faire. On peut se demander toutefois dans quelle mesure cette règle de l'art est respectée quand on voit toutes les cochonneries qui agrémentent une page web, à commencer par les boutons Facebook et autres Addthis qui utilisent le js à profusion, sans parler des autres bidules de types flash et les connections aux 15 ressources extérieures pour tout et n'importe quoi.

Il y a 15 ans, on mettait en avant des gifs animés pour alourdir les pages, aujourd'hui c'est dans l'arrière-boutique qu'on charge la mule. Faut bien de la fibre optique pour tout ce foutoir !

gravatar
Oni_Shadow a dit :

Il me semblait que tout navigateur moderne téléchargeait le JS indépendament de sa position dans le code contrairement à ce qui etait fait il y a quelques années, cette astuce n'étant donc plus d'actualité. Je me trompe?

gravatar
Titi_Alone a dit :

Deux attributs prometteurs qui permettront de placer le JS dans le "head", de façon optimisée : "async" et "defer", le premier sert à exécuter le script de façon asynchrone, ainsi, le JS est exécuté pendant que le parsage du HTML continue - de ce fait, le parsage du CSS aussi -, le second, lui permet au script de s’exécuter uniquement lorsque le parsage du HTML est terminé.

Au fait, le troisième lien de fin d'article est cassé.

gravatar
Meewan a dit :

Alors je vais me faire l'avocat du diable.

Dans un premier temps je suis d'accord avec ce que tu dis. C'est vrai pour 90% des pages (celles ou le js est juste la pour des animation ou pour fluidifier l'affichage) mais il reste 10% des pages ou je ne suis pas d'accord avec toi.

Ces 10% sont les pages qui reposent sur JS pour leur affichage. Tu vas me dire que c'est mal mais parfois on a simplement pas le choix. Par exemple une application web de carto (open street map ou google maps par exemple). Dans ce cas rendre le HTML vite n'a aucun intérêt car il n'y a rien (ou presque) à afficher. On ne va pas afficher des données JSON (ou n'importe quel autre format sérialisé de transport). On a besoin de toute façon de télécharger les JS pour rendre la page. A ce moment la il faut donc télécharger les JS le plus vite possible (regarde le source d'une page google map, leur js est directement dans la page et dans le head pour gagner des connexions) pour commencer a rendre la page très vite (potentiellement en fragmentant les js et en utilisant le téléchargement asynchrone).

Sinon bon article, ça fait plaisir de voir que je suis pas le seul taré qui cherche a comprendre comment ça marche pour optimiser.

gravatar
Le Hollandais Volant a dit :

@Meewan : j’ai hésité à parler des applications Web totalement en JS (Gmail, Facebook & co) où toute les données sont récupérées en Ajax et de façon asynchrone.
Dans ce cas, en effet, ça ne sert à rien de se casser la tête pour rien.

Néanmoins, je placerais quand même le JS en bas, ou au moins sous le CSS : comme ça, les nouvelles données qui arrivent (via JS) aurait déjà un style et se placeront correctement tout de suite, alors que si le CSS vient après, les données qui sont ajoutées par JS n’ont par de styles.

Après, tout ceci est valable surtout pour les connexions en mousse (2G, réseau pourri, etc.). Si on a la fibre 1 GBps, personne ne verra la différence.

gravatar
okh a dit :

@Oni_Shadow : C'est hautement probable que le navigateur ait une fonctionnalité de pré parsage pour déterminer les ressources à importer(pour ne pas avoir une liste d'attente de téléchargement vide pendant un moment), mais si le document est parsé en totalité, c'est qu'il a déja été téléchargé en entier et donc que le rendu a déja commencé depuis un moment.

Le problème reste le même. Si le rendu a le temps de croiser un script JS avant que le HTML soit téléchargé en entier(et donc que le parsage de toutes les ressources n'a pas encore été fait), le navigateur devra le télécharger en urgence. Sans compter qu'en plus, il y a deux parties à prendre en compte: le téléchargement (qui peut être fait en avance, par exemple en parsant le document une fois recu en entier), mais aussi l'éxécution du script, qui dépends nécessairement de la position du script dans la page(même si on peut demander à un script de ne s'éxecuter qu'en fin de page). L'execution peut parfois être très longue, d'autant qu'en JS, les calculs sont réalisés par les machines clientes, qui ne sont pas forcément très puissantes(contrairement aux langages serveurs ou la maitrise est totale)

gravatar
ArcturusB a dit :

Timo, ou comment rendre intéressants ce genre de sujets. :)

Les commentaires sont fermés pour cet article