Éviter les peintures est essentiel pour obtenir un taux de rafraîchissement fluide, en particulier sur mobile. Cependant, il arrive parfois que des peintures apparaissent dans les endroits les plus insolites. Cet article explique pourquoi les GIF animés peuvent entraîner des peintures inutiles et la solution remarquablement simple que vous pouvez appliquer.
Couches de beauté
Comme vous le savez probablement, les navigateurs modernes peuvent peindre des groupes d'éléments DOM dans des "images" distinctes, appelées calques. Parfois, il n'y a qu'une seule couche pour l'ensemble de la page, parfois il y en a des centaines, et dans de rares cas, des milliers.
Lorsque des éléments DOM sont regroupés dans une couche et que l'un d'eux change visuellement, nous devons peindre non seulement l'élément modifié, mais aussi tous les autres éléments de la couche qui se chevauchent avec l'élément modifié. Si vous peignez un élément par-dessus un autre, les pixels écrasés sont "perdus" pour toujours. Si vous souhaitez récupérer les pixels d'origine, vous devez les repeindre.
Par conséquent, nous souhaitons parfois isoler un élément des autres afin que, lorsqu'il sera peint, nous n'ayons pas besoin de repeindre les autres éléments qui n'ont pas changé. Par exemple, lorsque vous combinez un en-tête de page fixe avec du contenu à faire défiler, vous devez repeindre l'en-tête chaque fois que le contenu défile, ainsi que le contenu nouvellement visible. En plaçant l'en-tête dans une couche distincte, le navigateur peut optimiser le défilement. Lorsque vous faites défiler la page, le navigateur peut déplacer les calques (probablement avec l'aide du GPU) et éviter de les repeindre.
Chaque couche supplémentaire augmente la consommation de mémoire et ajoute une surcharge de performances. L'objectif est donc de regrouper la page en aussi peu de couches que possible tout en conservant de bonnes performances.
Qu'est-ce que tout cela a à voir avec les GIF animés ?
Voyons cette image:

Voici une configuration de couches potentielle pour une application simple. Il y a quatre couches: trois d'entre elles (les couches 2 à 4) sont des éléments d'interface ; la couche arrière est un chargeur, qui se trouve être un GIF animé. Dans le flux normal, vous affichez le chargeur (couche 1) pendant le chargement de votre application, puis, une fois le chargement terminé, vous affichez les autres couches. Mais voici l'essentiel: vous devez masquer le GIF animé.
Mais pourquoi dois-je le cacher ?
Bonne question ! Dans un monde idéal, le navigateur vérifierait simplement la visibilité du GIF pour vous et éviterait de le peindre automatiquement. Malheureusement, vérifier si le GIF animé est masqué ou visible à l'écran est généralement plus coûteux que de simplement le peindre. Il est donc peint.
Dans le meilleur des cas, le GIF se trouve dans sa propre couche, et le navigateur n'a qu'à le peindre et l'importer dans le GPU. Toutefois, dans le pire des cas, tous vos éléments peuvent être regroupés dans un seul calque, et le navigateur doit repeindre chaque élément. Et, une fois terminé, il doit toujours importer tout sur le GPU. Tout ce travail est effectué pour chaque frame du GIF, même si l'utilisateur ne peut même pas le voir.
Sur les ordinateurs de bureau, vous pouvez probablement vous permettre ce type de comportement de peinture, car les processeurs et les GPU sont plus puissants, et la bande passante est suffisante pour transférer des données entre les deux. Toutefois, sur mobile, la peinture est extrêmement coûteuse. Vous devez donc faire preuve de la plus grande prudence.
Quels navigateurs sont concernés ?
Comme souvent, les comportements varient d'un navigateur à l'autre. Aujourd'hui, Chrome, Safari et Opera redessinent tous les éléments, même si le GIF est masqué. Firefox, en revanche, comprend que le GIF est masqué et qu'il n'a pas besoin d'être repeint. Internet Explorer reste une sorte de boîte noire. Même dans IE11, les outils F12 étant encore en cours de développement, il n'est pas possible de savoir si un nouveau rendu est effectué ou non.
Comment savoir si je rencontre ce problème ?
Le moyen le plus simple est d'utiliser "Afficher les rectangles de peinture" dans les outils pour les développeurs Chrome. Chargez les outils de développement, appuyez sur la roue dentée en bas à droite (), puis sélectionnez Afficher les rectangles de peinture dans la section Rendu.

Il vous suffit maintenant de rechercher un rectangle rouge comme celui-ci:

La petite boîte rouge à l'écran indique que Chrome est en train de repeindre quelque chose. Vous savez qu'un GIF de chargement est masqué derrière les autres éléments. Par conséquent, lorsque vous voyez une zone rouge comme celle-ci, vous devez masquer les éléments visibles et vérifier si vous avez laissé le GIF animé tourner. Si c'est le cas, vous devez ajouter du CSS ou du JavaScript pour appliquer display: none
ou visibility: hidden
à cet élément ou à son élément parent. Bien sûr, si il ne s'agit que d'une image de fond, vous devez la supprimer.
Pour voir un exemple de ce comportement sur un site en ligne, consultez Allegro, où l'image de chaque produit est accompagnée d'un GIF de chargement masqué plutôt que masqué explicitement.
Conclusion
Pour atteindre 60 FPS, vous devez uniquement effectuer ce qui est nécessaire pour afficher la page. Pour y parvenir, il est essentiel d'éliminer l'excès de peinture. Les GIF animés laissés en cours d'exécution peuvent déclencher des peintures inutiles, que vous pouvez facilement trouver et déboguer à l'aide de l'outil "Afficher les rectangles à peindre" de DevTools.
Vous n'avez pas laissé ce GIF de chargement animé de chaton tourner en boucle, n'est-ce pas ?