CSS e web

Desempenho dos gradientes CSS: os gradientes abrandam um site?

Um gradiente CSS estático é quase gratuito. Os custos vêm do que as pessoas fazem com os gradientes: desfocados enormes, fundos que se repintam ao deslocar e animações que nunca páram. Eis como distinguir.

GradientlyConta Gradiently verificada··7 min de leitura
Capa: Burnt Mist · GR·3M7T·BR

A versão curta

  • Um gradiente CSS estático custa quase nada a carregar, porque é uma linha de texto e não um ficheiro para descarregar e descodificar.
  • Os gradientes custam tempo de pintura, que cresce com a área pintada e o número de camadas, mas um gradiente estático é pintado uma vez e depois reutilizado.
  • Os riscos reais de desempenho são os filtros de desfocado grandes, os fundos que se repintam ao deslocar e as animações de gradiente que repintam a cada fotograma.
  • Animar o transform ou a opacity numa camada de gradiente costuma ser muito mais barato do que animar o background-position ou as paragens de cor.
  • A única resposta fiável para uma página concreta é medi-la, com o paint flashing e uma gravação de Performance nas ferramentas de programador do navegador.
Nesta página

Um bom desempenho dos gradientes CSS é o caso normal: um gradiente estático não abranda um site de forma que se note. É uma linha de texto, por isso não há nada para descarregar, nada para descodificar e nada por que esperar. Os gradientes custam um pouco de tempo de pintura, como qualquer outra cor da página. As páginas lentas vêm de alguns padrões específicos construídos sobre gradientes: desfocados grandes, repinturas ao deslocar e animações que repintam a cada fotograma. Este guia mostra qual é qual e como verificar a tua própria página.

Carregamento: gradientes contra imagens

background: linear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6); tem 67 carateres. Chega dentro da tua folha de estilos, não precisa de um pedido extra e desenha-se nítido em qualquer tamanho e densidade de píxeis. Um fundo em imagem precisa do seu próprio pedido, tem de ser descodificado antes de poder ser desenhado e tem de ser grande o suficiente para ecrãs grandes e de alta densidade.

67 carateres de CSSlinear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6)
Este fundo inteiro, em qualquer tamanho, custa menos do que uma frase de texto a carregar.
FundoDescargaMemória descodificada a 1920×1080
Gradiente CSSAlgumas dezenas de bytes no teu CSSSem bitmap para guardar; pintado conforme necessário
Imagem comprimida (AVIF, WebP, JPEG)Um ficheiro à parte, muitas vezes de dezenas a centenas de quilobytesCerca de 8,3 MB (largura × altura × 4 bytes)
A mesma imagem a 3840×2160 para 4K nítidoAinda maiorCerca de 33 MB
As imagens descodificadas são guardadas como bitmaps completos, seja qual for o tamanho do ficheiro. Os valores de memória são aritmética simples: píxeis vezes quatro bytes.

Portanto, para fundos simples e moderadamente sobrepostos, o CSS ganha sempre no carregamento. As imagens continuam a fazer sentido quando o fundo é genuinamente complexo, como um gradiente de malha pictórico com muitos pontos de cor ou uma textura fotográfica. Nesse caso, a troca é peso do ficheiro por riqueza visual, e muitas vezes compensa.

Pintura: o que custa um gradiente no ecrã

Para mostrar um gradiente, o navegador calcula uma cor para cada píxel que cobre: isso é pintar. O trabalho cresce com a área pintada, o número de camadas de gradiente empilhadas e quaisquer efeitos por cima. Para um fundo estático acontece uma vez, e o resultado é reutilizado enquanto te deslocas ou interages, a não ser que algo o invalide.

Pintado uma vez

  • Um gradiente estático num cartão ou herói
  • Vários brilhos radiais sobrepostos que não se movem
  • Uma textura de ruído em mosaico sobre um gradiente
  • Uma borda com gradiente desenhada com fundos

Pintado vezes sem conta

  • Animar o background-position ou as paragens de cor
  • background-attachment: fixed ao deslocar
  • Desfocado com backdrop-filter sobre conteúdo em movimento
  • Um elemento com gradiente que muda continuamente de tamanho

Os riscos reais: desfocado, fundos fixos e animação

Desfocados grandes. O filter: blur() e o backdrop-filter recolhem muitos píxeis vizinhos para cada píxel, e o trabalho cresce tanto com o raio do desfocado como com a área. Um gradiente desfocado pintado uma vez costuma estar bem. Um backdrop-filter sobre conteúdo que se desloca por baixo tem de ser recalculado à medida que esse conteúdo se move, e é aí que as interfaces de glassmorphism tendem a engasgar em telemóveis modestos.

Fundos fixos. O background-attachment: fixed mantém um fundo parado enquanto a página se desloca, o que pode obrigá-lo a repintar a cada passo de deslocação. Se queres um gradiente que fique no sítio, um elemento com position: fixed por trás do conteúdo costuma ser mais barato, porque o navegador o pode mover como uma camada à parte.

Animação. Mover o background-position ou animar paragens de cor com @property repinta o elemento a cada fotograma. Num botão isso é trivial. Num herói de ecrã inteiro, é trabalho contínuo enquanto a página estiver aberta, o que se nota em calor e desgaste da bateria nos telemóveis.

css
/* repaints the whole hero every frame */
.hero--costly {
  background: linear-gradient(120deg, #1e1b4b, #7c3aed, #f472b6);
  background-size: 300% 300%;
  animation: pan 12s ease-in-out infinite alternate;
}

/* the browser can usually just move a finished layer */
.hero--cheap::before {
  content: "";
  position: absolute;
  inset: -50%;
  z-index: -1;
  background: conic-gradient(#1e1b4b, #7c3aed, #f472b6, #1e1b4b);
  animation: turn 40s linear infinite;
}

@keyframes pan { to { background-position: 100% 50%; } }
@keyframes turn { to { transform: rotate(1turn); } }
Dois heróis animados. O segundo anima o transform, que os navegadores costumam conseguir tratar no compositor sem repintar.

O guia sobre o gradiente animado em CSS tem o conjunto completo de técnicas, das mais baratas às mais flexíveis.

Camadas e will-change

Promover um elemento à sua própria camada do compositor, com will-change: transform ou uma animação de transform ativa, é o que torna possível uma animação barata. Não é gratuito: cada camada guarda o seu próprio bitmap na memória gráfica, aproximadamente largura × altura × 4 bytes em píxeis do dispositivo. Uma camada sobredimensionada para o fundo de um herói está bem. Dezenas de cartões promovidos, cada um com a sua camada de gradiente, podem gastar mais memória do que poupam em tempo de pintura. Acrescenta will-change aos elementos que realmente animam, não como regra geral.

PadrãoTrabalho do navegadorAlternativa mais barata
background-position animado num heróiRepintar a cada fotogramatransform numa camada de gradiente sobredimensionada
background-attachment: fixedRepintar ao deslocarUma camada de gradiente com position: fixed por trás do conteúdo
backdrop-filter sobre conteúdo que se deslocaDesfocado recalculado à medida que o conteúdo se moveUma camada estática pré-desfocada, ou uma área desfocada mais pequena
Filtro de ruído SVG ao vivo num elemento grandeO filtro corre sobre cada píxel repintadoUma pequena imagem de ruído em mosaico
will-change em todos os cartõesMuitas camadas guardadas na memória gráficawill-change só no que anima
Padrões comuns de gradiente, o que fazem o navegador fazer e a forma mais leve de obter o mesmo aspeto.

Como medir o desempenho dos gradientes

  1. 1

    Ativa o paint flashing

    Nas DevTools do Chrome, abre o painel Rendering e ativa o Paint flashing. Tudo o que pisca a verde quando nada devia estar a mudar está a ser repintado.

  2. 2

    Grava um traço de Performance

    Grava alguns segundos de deslocação ou de animação parada no painel Performance. Vê quanto de cada fotograma se gasta em pintura e se há fotogramas perdidos.

  3. 3

    Limita o CPU

    Usa a limitação de CPU do painel Performance para simular um dispositivo mais lento. Um herói que corre suave num portátil rápido pode ter dificuldades num telemóvel de gama média.

  4. 4

    Vê o painel Layers

    Vê quantas camadas de compositor existem e quanta memória usam. Um número inesperadamente alto de camadas costuma significar que o will-change é usado em excesso.

  5. 5

    Testa o dispositivo real

    Termina num telemóvel a sério. O calor e o desgaste da bateria de uma animação constante passam facilmente despercebidos num computador.

O guia da web.dev sobre desempenho de renderização explica o pipeline por trás destas ferramentas: estilo, layout, pintura e composição. Saber que fase o teu gradiente desencadeia diz-te se é barato.

Uma lista de verificação de desempenho para gradientes

  • Usa gradientes CSS para fundos simples e sobrepostos; imagens só quando o visual realmente as exige.
  • Mantém os raios de desfocado modestos e evita o backdrop-filter sobre áreas grandes que se deslocam.
  • Substitui o background-attachment: fixed por uma camada de posição fixa.
  • Anima o transform ou a opacity, não o background-position, em áreas grandes.
  • As animações lentas e ambiente podem parar por completo para quem usa movimento reduzido.
  • Acrescenta grão como uma pequena imagem em mosaico, não como um filtro SVG ao vivo num elemento grande; vê a textura de ruído em CSS.
  • Mede antes e depois com o paint flashing e uma gravação de Performance.

Perguntas frequentes

Os gradientes CSS abrandam um site?

Os gradientes CSS estáticos não o fazem de forma que se note. Não precisam de descarga e são pintados uma vez. Os desfocados grandes, os fundos fixos e a animação constante é que custam desempenho.

Um gradiente CSS é mais rápido do que uma imagem de fundo?

Normalmente sim. Um gradiente são algumas dezenas de bytes de CSS sem pedido nem descodificação, enquanto uma imagem precisa de uma descarga e fica na memória como um bitmap completo.

Os gradientes animados são maus para o desempenho?

Animar o background-position ou as paragens de cor repinta a cada fotograma, o que importa em áreas grandes. Animar o transform ou a opacity numa camada de gradiente costuma ser muito mais barato.

Porque é lento o meu fundo em gradiente desfocado?

O desfocado recolhe muitos píxeis vizinhos para cada píxel, por isso o custo cresce com o raio e a área. É pior com backdrop-filter sobre conteúdo que se desloca ou anima.

Como verifico se o meu gradiente está a ser repintado?

Ativa o Paint flashing no painel Rendering das DevTools do Chrome. As áreas que continuam a piscar com a página parada estão a ser repintadas.

Partilhar este guia

Escrito pela GradientlyConta Gradiently verificada

A equipa por trás da Gradiently, uma ferramenta de design construída em torno dos Marks: gradientes vivos que fazem tudo o que crias parecer teu.

Ver o nosso perfil