"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Les deux lignes de CSS qui ont miné les performances (fps en ps)

Les deux lignes de CSS qui ont miné les performances (fps en ps)

Publié le 2024-11-03
Parcourir:839

J'ai récemment publié Learn WCs et si vous l'avez vu, vous avez probablement remarqué l'animation en arrière-plan, où les cercles colorés se déplacent en diagonale sur l'écran. Cela ressemble à ceci :

Cela fonctionne bien sur Chrome et Safari, mais j'ai remarqué une forte baisse des performances sur Firefox.

Les performances étaient si mauvaises que j'ai directement désactivé cette animation dans Firefox.

Comment fonctionne l'animation ?

L'animation est construite à l'aide de deux div imbriqués. Le div externe est le premier enfant de la balise body du site.

    

L'élément .background-gradient est chargé de créer un dégradé qui s'étend sur toute la largeur et la hauteur de son conteneur parent. Comme ceci :

The Two Lines of CSS That Tanked Performance (fps to ps)

Le masque .background-mask externe est responsable de deux choses :

  1. Il définit la position sur fixe et fait en sorte que le conteneur remplisse toutes les dimensions de la fenêtre.
  2. Crée un masque en pointillés sur le dégradé

Cela garantit que la couleur des points est la couleur du dégradé directement en dessous :

The Two Lines of CSS That Tanked Performance (fps to ps)

Voici le CSS pour tout ce que j'ai décrit ci-dessus :

.background-mask {
    --mask-size: 24px;

    /* Position Styles */
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: -1;

    /* Mask Styles */
    mask-image: radial-gradient(black 2px, transparent 2px);
    mask-size: var(--mask-size) var(--mask-size);
    mask-position: 0px 0px;
    animation: mask-move 3s infinite linear;
}

.background-gradient {
    background: var(--red);
    background-image: var(--gradient);
    width: 100%;
    height: 100%;
}

@keyframes mask-move {
    0% {
        mask-position: 0px 0px;
    }

    100% {
        mask-position: var(--mask-size) var(--mask-size);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero-background-mask {
        animation: none;
    }
}

Si vous souhaitez en savoir plus sur les masques en CSS, je peux vous recommander cet article complet d'Ahmad Shadeed

Quelle est la cause de cette baisse de performances ?

Toutes les propriétés CSS ne s'animent pas de la même manière. Sans trop entrer dans la façon dont le navigateur affiche le code HTML sur la page (même si je l'ai décrit ici), il passe par une poignée d'étapes. Les trois étapes qui nous intéressent sont :

  • Mise en page - Lorsque le navigateur calcule la taille et les positions des éléments sur la page
  • Paint - Dessine tous les aspects visuels de la page, comme les images, les couleurs, les ombres, etc.
  • Composite - Superposer les éléments les uns sur les autres dans le bon ordre

L'ordre du pipeline ressemble à ceci :

Mise en page → Peinture → Composite

Les processus de mise en page et de peinture peuvent être gourmands en CPU, il est donc important d'essayer de réduire le nombre de fois où votre CSS déclenche les étapes du pipeline*.* Le navigateur aide dans une certaine mesure en optimisant les performances de certaines propriétés, d'autres ignorez des étapes entières du pipeline de rendu et d'autres peuvent tirer parti de l'accélération matérielle pour déplacer le calcul du CPU vers le GPU.

L'animation de certaines propriétés, comme translation et opacity , évite de déclencher une mise en page et utilise l'accélération matérielle.

Malheureusement, ce n'est pas le cas lors de l'animation de la position du masque. J'ai jeté un œil à Chrome et j'ai vu que le nombre de peintures pour le div d'arrière-plan augmentait à chaque image. Au bout de quelques secondes, il avait déjà déclenché une peinture plus de 1 000 fois.

The Two Lines of CSS That Tanked Performance (fps to ps)

Même avec ce nombre de peintures élevé, l'animation sur Chrome est fluide. Cependant, cela semble super bizarre sur Firefox. Malheureusement, je n’ai pas trouvé de moyen de mesurer le nombre de peintures sur Firefox, donc toutes les hypothèses que je fais sur les mauvaises performances de Firefox ne sont que des conjectures.

Ce que j'ai remarqué, c'est que l'animation convient aux petits appareils, mais s'aggrave à mesure que la taille de l'écran augmente. Ma théorie de travail est que Firefox ne regroupe pas les déclencheurs de mise en page pour chacun des masques 24x24, ce qui provoque un ralentissement du FPS lorsque davantage de masques 24x24 sont présents. Encore une fois, je me trompe peut-être complètement.

Comment ai-je résolu ce problème ?

Au lieu d'animer des propriétés CSS mal optimisées comme mask-position , je devais m'appuyer sur les propriétés les plus performantes, comme Translate.

La solution n'était pas de déplacer les masques de 24 pixels, mais de déplacer tout l'élément d'arrière-plan à l'aide de la propriété Translate.

D'un point de vue abstrait, voici à quoi ressemble l'animation :

Voici le changement de deux lignes dans le CSS :

/* --mask-size = 24px */

@keyframes mask-move {
    0% {
        transform: translate(calc(var(--mask-size) * -1), calc(var(--mask-size) * -1));
    }

    100% {
        transform: translate(0px, 0px);
    }
}

Le navigateur n'anime plus la position du masque, ce qui déclenchait une mise en page sur chaque image. Même si l’arrière-plan bouge sur chaque image, la translation ne déclenche pas de mise en page ni de peinture. Vous pouvez voir que le seul peint deux fois, contre 1 000 par minute.

The Two Lines of CSS That Tanked Performance (fps to ps)

Les téléspectateurs aux yeux d’aigle auront repéré un problème. Si vous vous en souvenez, la hauteur et la largeur de l'arrière-plan remplissent la fenêtre. Déplacer l'arrière-plan vers la gauche et vers le haut de 24 pixels nous laisse cet espace vide dans la fenêtre.

The Two Lines of CSS That Tanked Performance (fps to ps)

Le résoudre est aussi simple que d'ajouter la taille du masque à la largeur et à la hauteur du conteneur :

.background-mask {
    --mask-size: 24px;

    width: calc(100%   var(--mask-size));
    height: calc(100%   var(--mask-size));
}

Regardons à nouveau Firefox :

Ce n'est peut-être pas une solution parfaite, mais c'est toujours un peu satisfaisant de réaliser une astuce CSS amusante fumée et miroirs.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/andrico1234/the-two-lines-of-css-that-tanked-performance-120fps-to-40fps-3lnj?1 En cas de violation, veuillez contacter study_golang @163.com supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3