Optimisation des performances en CSS

Brouillon

Cette page n'est pas terminée.

Afficher une page sans mise en forme, puis ré-afficher cette même page une fois sa mise en forme chargée serait un processus bien désagréable pour l'utilisateur. Afin d'éviter ce désagrément, le CSS retarde l'affichage de la page sur le naviguateur tant qu'il n'a pas été entièrement chargé et interprêté : on dit que le CSS bloque le rendu de la page (on le qualifie d'ailleurs de "render blocking" en anglais). C'est cette configuration que le navigateur utilise par défaut, bien que l'on puisse spécifier une stratégie d'affichage différente comme indiqué dans la section suivante.

Le navigateur suit une procédure d'affichage très précise : l'affichage n'intervient qu'après la mise en page, qui elle-même dépend de la génération de l'abre de rendu par le navigateur, qui requiert lui aussi l'existence de deux autres ressources : le DOM (Document Object Model) et le CSSOM (CSS Object Model). Optimiser les performances en CSS revient donc d'une part à réduire le temps de chargement des ressources, et d'autre part à optimiser la construction du CSSOM. Pour se faire, quelques bonnes pratiques :

  • Retirez les règles de styles inutilisées ou dupliquées,
  • Minimisez la taille de votre fichier CSS (en retirant les espaces, retours à la ligne et tabulations par exemple),
  • compressez votre fichier CSS et enregistrez-le dans le cache du navigateur client,
  • enregistrez dans des fichiers additionnels les règles CSS qui ne sont pas nécessaires lors du chargement de la page afin de diminuer le temps de bloquage.

Optimiser le temps de bloquage du rendu

Une des forces du CSS réside dans sa capacité à appliquer des styles différents selon l'appareil utilisé, par le biais de Requêtes Média ("media queries" en anglais) permettant de poser des conditions de mise en page selon les caractéristiques de l'apareil. Ces requettes média sont d'une importance capitale pour le responsive design (mise en page flexible) et peuvent également nous permettre d'optimiser une partie critique du processus de rendu. En effet, le navigateur bloque le rendu de la page tant qu'il n'a pas entièrement interprêté les règles CSS, mais ne bloquera plus ni le rendu, ni l'affichage pour des fichiers CSS dont il sait ne pas avoir l'utilité - comme c'est le cas pour la mise en page d'impression papier, destinée à l'imprimante et non à l'écran. En réorganisant alors l'ensemble des règles CSS en plusieurs fichiers suivant des requêtes média, nous pouvons alors éviter de bloquer inutilement le rendu en attendant le chargement de ressources superflues pour l'affichage.

Pour obtenir ce résultat dans les faits, il suffit de placer le code CSS inutilisé lors du rendu, par exemple celui de l'impression papier, dans un fichier à part puis de l'intégrer à la page par le biais d'une balise <link>. On spécifie ensuite l'attribut media de cette balise pour y ajouter notre requête média : dans notre exemple, cette requête spécifierait que ce n'est utile que pour une imprimante.

<link rel="stylesheet" href="styles.css"> <!-- bloquant -->
<link rel="stylesheet" href="print.css" media="print"> <!-- non bloquant -->
<link rel="stylesheet" href="mobile.css" media="screen and (max-width: 480px)"> <!-- non boquant sur grand écran -->

Par défaut, le navigateur suppose que chaque fichier CSS est bloquant, car probablement utile pour le rendu. En utilisant cet attribut media, le navigateur comprend alors quel fichier utiliser dans quel scénario : il téléchargera alors le fichier, mais ne bloquera pas le rendu lors de son interprétation, ce qui résultera en un affichage plus rapide pour l'utilisateur. Dans le cas ci-dessus, le fichier styles.css est boquant quelque soit l'appareil utilisé, print.css devient bloquant pour une imprimante et mobile.css devient bloquant seulement lorsque la largeur de l'écran n'excède pas 480 pixels.

Interprêter les animations sur le GPU

Les navigateurs sont déjà optimisés pour manipuler les animations CSS, ainsi que les propriétés d'animation qui ne provoquent pas de réorganisation soudaine du document (ces autres propriétés nécessiteront alors un nouveau rendu). Cette optimisation s'effectue en plaçant les éléments animés sur un autre fil d'execution que l'on peut alors envoyer sur le GPU, bien plus rapide pour ce genre de tâche. Pour profiter de cette optimisation, il faut alors animer de préférence avec les propriétés de transformation 3D (transform: translateZ(), rotate3d(), etc.), de transformation 2D ainsi que les propriétés opacity, position: fixed, will-change et filter. D'autres éléments, parmi lesquels <video>, <canvas> ou encore <iframe>, fonctionnent aussi sur leur propre fil d'execution. Cette technique permet donc de tirer profit de la vitesse d'exécution du GPU pour chaque élément géré sur un nouveau fil d'éxécution, et permet d'obtenir de bien meilleures performance, en particulier sur mobile.

La propriété will-change

La propriété CSS will-change indique au navigateur les propriétés CSS d'un élément qui sont suceptibles d'être modifiés par la suite (lors d'animations par exemple), afin que le navigateur puisse s'y préparer et optimiser ces changements. Cela permet principalement d'améliorer les performances en réalisant en amont des calculs parfois gourmands.

will-change: opacity, transform;

La propriété font-display

Insérée dans une règle @font-face, la propriété CSS font-display permet de définir la logique de chargement et d'affichage des polices par le navigateur. Elle permet par exemple d'afficher le texte avec une police par défaut le temps que l'autre charge ou lorsque le chargement échoue. Cela permet de rendre le texte visible sans l'attente du chargement des polices, mais a pour défaut un flash brusque de changement de police une fois la ressource chargée.

@font-face {
  font-family: someFont;
  src: url(/path/to/fonts/someFont.woff) format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: fallback;
}

Dans cet exemple, la dernière règle font-display: fallback; permet justement d'afficher le texte avec une police par défaut en attendant le chargement de la police someFont.woff.

La propriété contain

La propriété CSS contain permet quant à elle de spécifier au navigateur qu'un élément et son contenu sont, dans la mesure du possible, indépendant du reste de l'arborescence du document. Ceci offre la possibilité au navigateur de recalculer la mise en page, le style, le rendu, la taille ou toute combinaison de ces propriétés seulement pour une portion de l'arborescence DOM, sans avoir à étendre ces calculs à la totalité de la page.

Conclusion

Optimiser les performances en CSS revient ainsi à améliorer deux étapes cruciales et chronophages du rendu de page :

  • d'une part le chargement des ressources CSS de la page (en compressant, en divisant le fichier, ou encore en l'enregistrant dans le cache par exemple),
  • d'autre part le rendu, en établissant une stratégie ingénieuse de chargement et d'interprétation des ressources, notamment en distinguant les ressources essentielles pour le rendu et les autres ressources annexes, qui peuvent attendre;

Enfin, les outils de développement du navigateur sont à votre disposition pour vous aider à cibler les étapes chronophages qui ralentissent le rendu de vos pages et gagner encore en efficacité, au prix parfois de quelques compromis.

Dans ce module

Voir aussi