CSS e web

Fundos com gradiente animado em CSS, como deve ser

Os gradientes não se podem animar diretamente, mas tudo à volta deles pode. Quatro técnicas, o que cada uma custa ao navegador e como manter o movimento calmo e opcional.

GradientlyConta Gradiently verificada··5 min de leitura
Capa: Pine Afternoon · GR·6MTX·YD

A versão curta

  • Os navegadores não conseguem interpolar entre dois valores de gradiente, por isso um gradiente animado em CSS move, esbate ou transforma o gradiente em vez de o animar diretamente.
  • A técnica clássica faz o fundo maior do que o elemento e anima o background-position, o que funciona em todo o lado mas volta a pintar a cada fotograma.
  • Registar propriedades personalizadas com @property permite ao navegador animar cores, ângulos e posições individuais dentro de um gradiente.
  • Animar o transform ou a opacity numa camada de gradiente separada costuma ser a opção mais barata, porque os navegadores muitas vezes conseguem compô-la sem voltar a pintar.
  • Toda a animação de gradiente deve parar, ou ficar quase imóvel, quando o utilizador pediu movimento reduzido.
Nesta página

Um gradiente animado em CSS é um fundo em gradiente que muda de cor ou de posição ao longo do tempo. Há um senão: se escreveres dois gradientes diferentes numa regra @keyframes, os navegadores não os misturam, saltam. Por isso, todas as técnicas que funcionam animam outra coisa junto ao gradiente: a sua posição, as propriedades personalizadas lá dentro ou a camada em que é pintado. A que escolheres decide a suavidade do resultado e o trabalho que o navegador faz a cada fotograma.

Três momentos de uma animação lenta. A direção e a cor movem-se, mas a paleta continua a ser de uma só família.

Para o lado do design, quando o movimento ajuda uma marca e como o ritmar, vê os fundos com gradiente animado. Este guia é o código.

Técnica 1: move um fundo maior do que o elemento

Faz o gradiente duas a quatro vezes maior do que o elemento com background-size e depois anima o background-position para que uma parte diferente apareça ao longo do tempo. Funciona em todos os navegadores e não precisa de JavaScript. Usa alternate para que o movimento se inverta com suavidade em vez de saltar de volta ao início.

css
.hero {
  background-color: #1e1b4b;
  background-image: linear-gradient(120deg, #1e1b4b, #7c3aed, #f472b6, #fb923c);
  background-size: 300% 300%;
  animation: pan 18s ease-in-out infinite alternate;
}

@keyframes pan {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}
O gradiente animado clássico. Durações lentas de 12 a 30 segundos parecem ambiente e não agitação.

O custo: o background-position não é algo que os navegadores consigam mover só na placa gráfica, por isso o elemento é repintado a cada fotograma. Num botão isso não é nada. Num herói de ecrã inteiro é trabalho real que corre enquanto a página estiver aberta.

Técnica 2: anima as paragens de cor com @property

As propriedades personalizadas são normalmente cadeias de texto, que não se podem interpolar. Registar uma com @property dá-lhe um tipo, como <color>, <angle> ou <percentage>, e as propriedades com tipo animam-se com suavidade. Usa-as dentro do gradiente e podes animar diretamente as cores, o ângulo ou a posição de uma paragem. O @property é suportado em todos os principais navegadores atuais; consulta o caniuse se suportares os mais antigos.

css
@property --from {
  syntax: "<color>";
  inherits: false;
  initial-value: #7c3aed;
}
@property --to {
  syntax: "<color>";
  inherits: false;
  initial-value: #f472b6;
}
@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 120deg;
}

.hero {
  background: linear-gradient(var(--angle), var(--from), var(--to));
  animation: shift 16s ease-in-out infinite alternate;
}

@keyframes shift {
  to {
    --from: #0891b2;
    --to: #fb923c;
    --angle: 200deg;
  }
}
Cores e ângulo a animar dentro do gradiente. As propriedades não registadas saltariam em vez de se misturarem.
As duas pontas da animação acima. O navegador mistura todos os fotogramas intermédios.

Esta técnica também volta a pintar a cada fotograma, como a primeira. A vantagem é o controlo: podes mover um só brilho num gradiente de malha, rodar uma borda cónica ou deslocar um gradiente de marca para uma segunda paleta sem fundos sobredimensionados.

Técnica 3: transforma uma camada de gradiente

Põe o gradiente num pseudoelemento muito maior do que o elemento e anima o seu transform, por exemplo uma rotação ou deriva lenta. Os navegadores costumam conseguir mover uma camada transformada na placa gráfica sem a repintar, por isso esta é a forma mais barata de animar um gradiente grande. O will-change: transform sugere que a camada seja promovida com antecedência.

css
.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.hero::before {
  content: "";
  position: absolute;
  inset: -50%;
  z-index: -1;
  background: conic-gradient(from 0deg, #1e1b4b, #7c3aed, #f472b6, #0891b2, #1e1b4b);
  animation: turn 40s linear infinite;
  will-change: transform;
}

@keyframes turn {
  to { transform: rotate(1turn); }
}
Um enorme gradiente cónico a rodar devagar atrás do conteúdo. O inset negativo mantém os cantos cobertos enquanto roda.

Técnica 4: fusão entre dois gradientes

Empilha duas camadas de gradiente e anima a opacity da de cima. A opacidade também é uma propriedade amiga do compositor, por isso a transição é suave e barata. Serve para mudanças lentas de ambiente, como uma paleta de dia a esbater-se numa de noite, e permite que os dois gradientes sejam completamente diferentes na estrutura.

css
.sky {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, #7dd3fc, #fde68a);
}

.sky::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, #0f172a, #7c3aed);
  animation: dusk 20s ease-in-out infinite alternate;
}

@keyframes dusk {
  from { opacity: 0; }
  to   { opacity: 1; }
}
O dia esbate-se em noite e volta. Só a opacidade muda, por isso nada é repintado.

Escolher uma técnica

TécnicaTrabalho do navegador por fotogramaMelhor para
Mover o background-positionRepintarElementos pequenos, botões, texto
Cores e ângulos com @propertyRepintarMudanças de cor precisas, bordas a rodar
transform numa camadaNormalmente só composiçãoFundos grandes, de ecrã inteiro
Fusão de opacityNormalmente só composiçãoMudanças lentas de ambiente ou de paleta
Repintar é aceitável em áreas pequenas. Para áreas grandes, prefere transform e opacity.

Mede em vez de adivinhar. Nas DevTools do Chrome, o painel Rendering com o paint flashing destaca as áreas repintadas a cada fotograma, e uma gravação no Performance mostra quanto de cada fotograma vai para a pintura. O guia sobre o desempenho dos gradientes CSS percorre o processo.

Movimento reduzido e boas maneiras

Algumas pessoas ficam tontas ou distraídas com o movimento de fundo, e os sistemas operativos permitem-lhes pedir menos. Respeita isso com uma consulta prefers-reduced-motion que pára a animação e deixa um fotograma imóvel e acabado. O guia sobre movimento reduzido explica o que conta como movimento que vale a pena remover.

css
@media (prefers-reduced-motion: reduce) {
  .hero,
  .hero::before,
  .sky::after {
    animation: none;
  }
}
Uma regra que pára todas as técnicas acima. Confirma que o fotograma que fica continua a parecer certo.

Evita

  • Ciclos mais rápidos do que cerca de 8 segundos em áreas grandes
  • Rotação de matiz arco-íris por toda a página
  • Movimento atrás de texto corrente que as pessoas precisam de ler
  • Animações que continuam a correr quando o separador está parado durante minutos a fio

Faz

  • Movimento lento e ambiente dentro de uma família de cor
  • Movimento no herói, quietude no conteúdo
  • Um fotograma calmo e imóvel para movimento reduzido
  • Testa num portátil modesto e num telemóvel, não só num computador rápido

Perguntas frequentes

Pode animar-se um gradiente CSS?

Não diretamente: os navegadores saltam entre dois valores de gradiente nos keyframes. Anima antes o background-position, propriedades personalizadas registadas usadas dentro do gradiente, ou o transform e a opacity de uma camada de gradiente.

Qual é a forma mais suave de animar um fundo com gradiente?

Animar o transform ou a opacity numa camada de gradiente separada, porque os navegadores costumam conseguir tratar disso sem repintar.

Como animo as cores de um gradiente em CSS?

Regista cada cor com @property usando syntax: "<color>", usa as propriedades no gradiente e altera-as nos @keyframes.

Os gradientes animados tornam a página lenta?

Os pequenos raramente importam. Os fundos animados grandes que repintam a cada fotograma podem custar bateria e fluidez, por isso prefere transform ou opacity e mede com as DevTools.

Como respeito o movimento reduzido nas animações de gradiente?

Põe uma regra animation: none dentro de @media (prefers-reduced-motion: reduce) para que os utilizadores que pedem menos movimento vejam um fotograma imóvel.

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