"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > As duas linhas de CSS que prejudicaram o desempenho (fps para ps)

As duas linhas de CSS que prejudicaram o desempenho (fps para ps)

Publicado em 2024-11-03
Navegar:157

Lançamos recentemente o Learn WCs e se você já viu, provavelmente notou a animação de fundo, onde os círculos coloridos se movem diagonalmente pela tela. Fica assim:

Funciona bem no Chrome e Safari, mas notei uma queda acentuada no desempenho no Firefox.

O desempenho foi tão ruim que desativei imediatamente essa animação no Firefox.

Como funciona a animação?

A animação é construída usando dois divs aninhados. O div externo é o primeiro filho da tag body do site.

    

O elemento .background-gradient é responsável por criar um gradiente que abrange toda a largura e altura de seu contêiner pai. Assim:

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

A .background-mask externa é responsável por duas coisas:

  1. Define a posição como fixa e faz com que o contêiner preencha todas as dimensões da janela de visualização.
  2. Cria uma máscara pontilhada sobre o gradiente

Isso garante que a cor dos pontos seja a cor do gradiente diretamente abaixo deles:

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

Aqui está o CSS para tudo que descrevi acima:

.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;
    }
}

Se você estiver interessado em aprender mais sobre máscaras em CSS, posso recomendar esta postagem abrangente de Ahmad Shadeed

O que está causando essa queda no desempenho?

Nem todas as propriedades CSS são animadas igualmente. Sem entrar muito em como o navegador renderiza HTML para a página (embora eu tenha descrito isso aqui), ele passa por vários estágios. Os três estágios nos quais estamos interessados ​​são:

  • Layout - Quando o navegador calcula o tamanho e as posições dos elementos na página
  • Paint - Desenha todos os aspectos visuais da página, como imagens, cores, sombras, etc
  • Composto - Colocar os elementos em camadas uns sobre os outros na ordem correta

A ordem do pipeline é semelhante a esta:

Layout → Pintar → Composto

Os processos de layout e pintura podem consumir muito a CPU, por isso é importante tentar reduzir a quantidade de vezes que seu CSS aciona os estágios no pipeline*.* O navegador ajuda em parte, otimizando o desempenho para determinadas propriedades, algumas pule estágios inteiros do pipeline de renderização e outros podem aproveitar a aceleração de hardware para mover a computação da CPU para a GPU.

Animar certas propriedades, como translate e opacity , evita o acionamento de um layout e usa aceleração de hardware.

Infelizmente, este não é o caso ao animar a posição da máscara. Dei uma olhada no Chrome e vi que a contagem de tintas para o div de fundo estava aumentando a cada quadro. Depois de alguns segundos, ele já havia acionado uma pintura mais de 1.000 vezes.

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

Mesmo com essa alta contagem de tintas, a animação no Chrome parece suave. No entanto, parece muito estranho no Firefox. Irritantemente, não consegui encontrar uma maneira de medir a contagem de tinta no Firefox, então qualquer suposição que eu faça sobre o baixo desempenho do Firefox é puramente conjectura.

O que percebi é que a animação é boa para dispositivos pequenos, mas piora à medida que o tamanho da tela aumenta. Minha teoria de trabalho é que o Firefox não agrupa os gatilhos de layout para cada uma das máscaras 24x24, o que faz com que o FPS diminua quando mais máscaras 24x24 estão presentes. Novamente, posso estar completamente errado aqui.

Como eu consertei isso?

Em vez de animar propriedades CSS mal otimizadas, como mask-position , eu precisava me apoiar nas propriedades de melhor desempenho, como translate.

A solução não foi mover as máscaras em 24px, mas sim mover todo o elemento de fundo usando a propriedade de tradução.

Do ponto de vista abstrato, a animação fica assim:

Aqui está a mudança de duas linhas no 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);
    }
}

O navegador não anima mais a posição da máscara, o que acionava um layout em cada quadro. Mesmo que o fundo se mova em cada quadro, através da tradução ele não aciona um layout ou pintura. Você pode ver que as únicas tintas duas vezes, abaixo das 1.000 por minuto.

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

Os espectadores mais atentos terão detectado um problema. Se você se lembra, a altura e a largura do plano de fundo preenchem a janela de visualização. Deslocar o fundo para a esquerda e para cima em 24px nos deixa com este espaço vazio na janela de visualização.

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

Resolver isso é tão simples quanto adicionar o tamanho da máscara à largura e altura do contêiner:

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

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

Vamos dar uma olhada novamente no Firefox:

Pode não ser uma solução perfeita, mas é sempre um pouco satisfatório fazer um truque CSS divertido de fumaça e espelhos.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/andrico1234/the-two-lines-of-css-that-tanked-performance-120fps-to-40fps-3lnj?1 Se houver alguma infração, entre em contato com study_golang @163.com excluir
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3