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.
L'animation est construite à l'aide de deux divs imbriqués. Le div externe est le premier enfant de la balise body du site.
<body> <div class="background-mask"> <div class="background-gradient"></div> </div> <!-- Rest of content --> </body>
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 ça :
Le masque .background externe est responsable de deux choses :
Cela garantit que la couleur des points est la couleur du dégradé directement en dessous :
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
Toutes les propriétés CSS ne s’animent pas de la même manière. Sans trop entrer dans les détails de la manière 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 :
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.
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.
Au lieu d'animer des propriétés CSS mal optimisées comme mask-position , j'avais besoin de m'appuyer sur les propriétés plus performantes, comme traduire.
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.
From an abstract standpoint, this is how the animation looks:
Here’s the two line change in the 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); } }
The browser no longer animates the mask-position, which triggered a layout on each frame. Even though the background moves on each frame, through translate it doesn’t trigger a layout or a paint. You can see that the only paints twice, down from 1,000+ every minute.
Eagle-eyed viewers will have spotted a problem. If you remember, the height and width of the background fills the viewport. Shifting the background left and up by 24px leaves us with this empty space in the viewport.
Solving it is as simple as adding the mask size to the width and height of the container:
.background-mask { --mask-size: 24px; width: calc(100% + var(--mask-size)); height: calc(100% + var(--mask-size)); }
Let’s take a look again in Firefox:
It may not be a perfect solution, but it’s always a little satisfying pulling off a fun smoke and mirrors CSS trick.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!