Pourquoi certaines animations sont-elles lentes ?

Les navigateurs récents peuvent animer deux propriétés CSS à moindre coût: transform et opacity. Si vous animez autre chose, il y a de fortes chances que vous n'obteniez pas une fréquence minimale de 60 images par seconde (FPS). Cet article explique pourquoi.

Performances de l'animation et fréquence d'images

Il est communément admis qu'une fréquence d'images de 60 FPS est la valeur cible lors de l'animation d'un élément sur le Web. Cette fréquence d'images garantit la fluidité de vos animations. Sur le Web, un cadre désigne le temps nécessaire pour effectuer toutes les tâches requises pour mettre à jour et repeindre l'écran. Si chaque frame ne se termine pas dans un délai de 16,7 ms (1 000 ms / 60 environ 16,7), les utilisateurs perçoivent le retard.

Le pipeline de rendu

Pour afficher un contenu sur une page Web, le navigateur doit suivre les étapes suivantes:

  1. Style: calculez les styles qui s'appliquent aux éléments.
  2. Mise en page: générez la géométrie et la position de chaque élément.
  3. Peinte: remplissez les pixels de chaque élément en calques.
  4. Composite: dessinez les calques à l'écran.

Ces quatre étapes sont appelées pipeline de rendu du navigateur.

Lorsque vous animez un élément sur une page déjà chargée, ces étapes doivent se reproduire. Ce processus commence à l'étape qui doit être modifiée pour que l'animation puisse avoir lieu.

Comme indiqué précédemment, ces étapes sont séquentielles. Par exemple, si vous animez un élément qui modifie la mise en page, les étapes de peinture et de composition doivent également s'exécuter à nouveau. Animer un élément qui modifie la mise en page est donc plus coûteux qu'un élément qui ne modifie que la composition.

Animer les propriétés de mise en page

Les modifications de mise en page impliquent de calculer la géométrie (position et taille) de tous les éléments affectés par la modification. Si vous modifiez un élément, la géométrie des autres éléments peut avoir besoin d'être recalculée. Par exemple, si vous modifiez la largeur de l'élément <html>, certains de ses enfants peuvent être affectés. En raison de la façon dont les éléments débordent et s'affectent les uns les autres, les modifications apportées plus bas dans l'arborescence peuvent parfois entraîner des calculs de mise en page jusqu'en haut.

Plus l'arborescence des éléments visibles est grande, plus il faut de temps pour effectuer des calculs de mise en page.

Propriétés de l'animation de la peinture

Le peinture est le processus qui permet de déterminer l'ordre dans lequel les éléments doivent être affichés à l'écran. Il s'agit souvent de l'exécution la plus longue de toutes les tâches du pipeline.

La plupart des opérations de peinture dans les navigateurs modernes sont effectuées à l'aide de rastériseurs logiciels. Selon la façon dont les éléments de votre application sont regroupés en couches, vous devrez peut-être peindre d'autres éléments que celui qui a été modifié.

Animer des propriétés composites

La composition est le processus qui consiste à séparer la page en calques, à convertir les informations relatives à son aspect en pixels (rastérisation) et à assembler les calques pour créer une page (composition).

C'est pourquoi la propriété opacity est incluse dans la liste des éléments bon marché à animer. Tant que cette propriété se trouve dans sa propre couche, les modifications apportées peuvent être gérées par le GPU au cours de l'étape de composition. Les navigateurs Chromium et WebKit créent une nouvelle couche pour tout élément qui comporte une transition ou une animation CSS sur opacity.

Qu'est-ce qu'une couche ?

En plaçant les éléments qui vont être animés ou transférés sur une nouvelle couche, le navigateur n'a besoin que de repeindre ces éléments, pas tout le reste. Vous connaissez peut-être le concept de Photoshop d'un calque contenant un ensemble d'éléments qui peuvent être déplacés ensemble. Les couches de rendu du navigateur sont similaires à cette idée.

Bien que le navigateur fasse un bon travail pour décider quels éléments doivent figurer sur une nouvelle couche, s'il en manque un, il existe des moyens de forcer la création du calque. Pour en savoir plus, consultez Créer des animations très performantes. Cependant, la création de nouvelles couches doit être faite avec précaution, car chaque couche utilise de la mémoire. Sur les appareils dont la mémoire est limitée, la création de couches peut entraîner davantage de problèmes de performances que ceux que vous essayez de résoudre. En outre, les textures de chaque calque doivent être importées dans le GPU. Par conséquent, vous risquez de rencontrer des contraintes de bande passante entre le processeur et le GPU.

Performances CSS et JavaScript

Vous vous demandez peut-être s'il est préférable d'utiliser du code CSS ou JavaScript pour les animations du point de vue des performances.

Les animations CSS et les animations Web (disponibles dans les navigateurs compatibles avec l'API) sont généralement gérées sur un thread appelé thread compositeur. Il est différent du thread principal du navigateur, où les styles, la mise en page, la peinture et JavaScript sont exécutés. Cela signifie que si le navigateur exécute des tâches coûteuses sur le thread principal, ces animations peuvent continuer sans être interrompues.

Comme expliqué dans cet article, d'autres modifications de transformation et d'opacité peuvent, dans de nombreux cas, être également gérées par le thread compositeur.

Si une animation déclenche un effet de peinture, de mise en page ou des deux, le thread principal doit effectuer le travail. Cela est vrai pour les animations CSS et JavaScript. Les frais généraux liés à la mise en page ou au dessin risquent d'éclipser tout travail associé à l'exécution CSS ou JavaScript, rendant ainsi la question moot.