"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Las dos líneas de CSS que arruinaron el rendimiento (fps a ps)

Las dos líneas de CSS que arruinaron el rendimiento (fps a ps)

Publicado el 2024-11-03
Navegar:614

Recientemente lancé Learn WCs y, si lo has visto, probablemente hayas notado la animación en el fondo, donde los círculos de colores se mueven en diagonal a través de la pantalla. Se ve así:

Funciona muy bien en Chrome y Safari, pero noté una grave caída en el rendimiento en Firefox.

El rendimiento fue tan malo que inmediatamente desactivé esta animación en Firefox.

¿Cómo funciona la animación?

La animación se crea utilizando dos divs anidados. El div externo es el primer hijo de la etiqueta del cuerpo del sitio.

    

El elemento .background-gradient es responsable de crear un degradado que abarca todo el ancho y alto de su contenedor principal. Así:

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

La máscara de fondo exterior es responsable de dos cosas:

  1. Establece la posición como fija y hace que el contenedor llene todas las dimensiones de la ventana gráfica.
  2. Crea una máscara de puntos sobre el degradado

Esto garantiza que el color de los puntos sea el color del degradado directamente debajo de ellos:

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

Aquí está el CSS de todo lo que describí anteriormente:

.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 está interesado en aprender más sobre máscaras en CSS, puedo recomendarle esta publicación completa de Ahmad Shadeed

¿Qué está causando esta caída en el rendimiento?

No todas las propiedades CSS se animan por igual. Sin entrar demasiado en cómo el navegador representa HTML en la página (aunque lo he descrito aquí), hay varias etapas por las que pasa. Las tres etapas que nos interesan son:

  • Diseño: cuando el navegador calcula el tamaño y las posiciones de los elementos en la página
  • Pintar: dibuja todos los aspectos visuales de la página, como imágenes, colores, sombras, etc.
  • Compuesto: superponer los elementos uno encima del otro en el orden correcto

El orden de la canalización se ve así:

Diseño → Pintura → Compuesto

Los procesos de diseño y pintura pueden consumir mucha CPU, por lo que es importante intentar reducir la cantidad de veces que su CSS activa las etapas del proceso*.* El navegador ayuda en parte al optimizar el rendimiento para ciertas propiedades, algunas omita etapas enteras del proceso de renderizado y otros podrán aprovechar la aceleración de hardware para mover el cálculo de la CPU a la GPU.

Al animar ciertas propiedades, como traducir y opacidad, se evita activar un diseño y se utiliza aceleración de hardware.

Lamentablemente, este no es el caso cuando se anima la posición de la máscara. Eché un vistazo a Chrome y vi que el recuento de pintura para el div de fondo aumentaba en cada cuadro. Después de unos segundos, ya había activado una pintura más de 1000 veces.

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

Incluso con este alto número de pinturas, la animación en Chrome se siente fluida. Sin embargo, se siente muy chiflado en Firefox. Lamentablemente, no pude encontrar una manera de medir el recuento de pintura en Firefox, por lo que cualquier suposición que haga sobre el bajo rendimiento de Firefox es pura conjetura.

Lo que sí noté es que la animación está bien para dispositivos pequeños, pero empeora a medida que aumenta el tamaño de la pantalla. Mi teoría de trabajo es que Firefox no agrupa los activadores de diseño para cada máscara de 24x24, lo que hace que el FPS se estanque cuando hay más máscaras de 24x24 presentes. Nuevamente, puede que esté completamente equivocado.

¿Cómo solucioné esto?

En lugar de animar propiedades CSS mal optimizadas como mask-position , necesitaba apoyarme en propiedades de mayor rendimiento, como traducir.

La solución no fue mover las máscaras 24px, sino mover todo el elemento de fondo usando la propiedad de traducción.

Desde un punto de vista abstracto, así es como se ve la animación:

Aquí está el cambio de dos líneas en el 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);
    }
}

El navegador ya no anima la posición de la máscara, lo que activaba un diseño en cada cuadro. Aunque el fondo se mueve en cada fotograma, a través de la traducción no se activa un diseño ni una pintura. Puedes ver que el único pinta dos veces, en comparación con 1000 por minuto.

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

Los espectadores con ojos de águila habrán detectado un problema. Si recuerdas, la altura y el ancho del fondo llenan la ventana gráfica. Desplazar el fondo hacia arriba y hacia la izquierda 24 píxeles nos deja con este espacio vacío en la ventana gráfica.

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

Resolverlo es tan sencillo como sumar el tamaño de la máscara al ancho y alto del contenedor:

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

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

Echemos un vistazo nuevamente en Firefox:

Puede que no sea una solución perfecta, pero siempre es un poco satisfactorio realizar un divertido truco CSS de humo y espejos.

Declaración de liberación Este artículo se reproduce en: https://dev.to/andrico1234/the-two-lines-of-css-that-tanked-performance-120fps-to-40fps-3lnj?1 Si hay alguna infracción, comuníquese con Study_golang @163.com eliminar
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3