CSS e web

Fundos com gradiente animado em CSS, do jeito certo

Gradientes não podem ser animados diretamente, mas tudo ao redor deles pode. Quatro técnicas, o que cada uma custa ao navegador e como manter o movimento calmo e opcional.

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

Resumindo

  • Os navegadores não conseguem interpolar entre dois valores de gradiente, então um gradiente animado em CSS move, esmaece ou transforma o gradiente em vez de animá-lo diretamente.
  • A técnica clássica deixa o fundo maior que o elemento e anima o background-position, o que funciona em todo lugar, mas repinta a cada quadro.
  • Registrar propriedades personalizadas com @property permite que o navegador anime cores, ângulos e posições individuais dentro de um gradiente.
  • Animar transform ou opacity em uma camada de gradiente separada costuma ser a opção mais barata, porque os navegadores muitas vezes conseguem compô-la sem repintar.
  • Toda animação de gradiente deve parar, ou ficar quase parada, quando o usuário pediu movimento reduzido.
Nesta página

Um gradiente animado em CSS é um fundo em gradiente que muda de cor ou de posição com o tempo. Há uma pegadinha: se você escrever dois gradientes diferentes em uma regra @keyframes, os navegadores não os misturam, eles pulam. Por isso, toda técnica que funciona anima outra coisa ao lado do gradiente: sua posição, as propriedades personalizadas dentro dele ou a camada em que ele é pintado. Qual você escolhe decide o quanto a animação fica suave e quanto trabalho o navegador faz a cada quadro.

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

Para o lado do design, quando o movimento ajuda uma marca e como dar o ritmo, veja fundos com gradiente animado. Este guia é o código.

Técnica 1: mova um fundo superdimensionado

Deixe o gradiente de duas a quatro vezes maior que o elemento com background-size e depois anime o background-position para que uma parte diferente apareça com o tempo. Funciona em todos os navegadores e não precisa de JavaScript. Use alternate para que o movimento se inverta suavemente em vez de pular 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 ambientes em vez de agitadas.

O custo: o background-position não é algo que os navegadores consigam mover só na placa de vídeo, então o elemento é repintado a cada quadro. Em um botão, isso não é nada. Em um hero de tela cheia, é trabalho de verdade que roda enquanto a página estiver aberta.

Técnica 2: anime as paradas de cor com @property

As propriedades personalizadas normalmente são textos, que não podem ser interpolados. Registrar uma com @property dá a ela um tipo, como <color>, <angle> ou <percentage>, e propriedades tipadas animam de forma suave. Use-as dentro do gradiente e você pode animar diretamente as cores, o ângulo ou a posição de uma parada. O @property é aceito em todos os principais navegadores atuais; confira o caniuse se você oferece suporte a navegadores 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 animando dentro do gradiente. Propriedades não registradas pulariam em vez de se misturar.
As duas pontas da animação acima. O navegador mistura cada quadro entre elas.

Essa técnica ainda repinta a cada quadro, como a primeira. A vantagem dela é o controle: você pode mover um único brilho em um gradiente de malha, girar uma borda cônica ou levar um gradiente da marca para uma segunda paleta sem fundos superdimensionados.

Técnica 3: transforme uma camada de gradiente

Coloque o gradiente em um pseudoelemento bem maior que o elemento e anime o transform dele, por exemplo uma rotação ou deriva lenta. Os navegadores costumam conseguir mover uma camada transformada na placa de vídeo sem repintá-la, então esse é o jeito mais barato de animar um gradiente grande. O will-change: transform avisa que a camada deve ser 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 gradiente cônico enorme girando devagar atrás do conteúdo. O inset negativo mantém os cantos cobertos enquanto ele gira.

Técnica 4: faça um fade cruzado entre dois gradientes

Empilhe duas camadas de gradiente e anime a opacity da de cima. A opacidade também é uma propriedade amigável ao compositor, então o fade é suave e barato. Serve para mudanças lentas de clima, como uma paleta de dia esmaecendo em uma paleta de noite, e deixa os dois gradientes serem completamente diferentes em 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 esmaece em noite e volta. Só a opacidade muda, então nada é repintado.

Escolhendo uma técnica

TécnicaTrabalho do navegador por quadroMelhor para
Mover o background-positionRepinturaElementos pequenos, botões, texto
Cores e ângulos com @propertyRepinturaMudanças precisas de cor, bordas giratórias
transform em uma camadaEm geral só composiçãoFundos grandes, de tela cheia
Fade cruzado com opacityEm geral só composiçãoMudanças lentas de clima ou de paleta
Repintar é aceitável em áreas pequenas. Para áreas grandes, prefira transform e opacity.

Meça em vez de adivinhar. No Chrome DevTools, o destaque de pintura do painel Rendering marca as áreas repintadas a cada quadro, e uma gravação de Performance mostra quanto de cada quadro vai para a pintura. Desempenho de gradientes em CSS mostra o passo a passo.

Movimento reduzido e boas maneiras

Algumas pessoas ficam tontas ou distraídas com movimento no fundo, e os sistemas operacionais permitem que peçam menos. Respeite isso com uma consulta prefers-reduced-motion que pare a animação, deixando um quadro parado e finalizado. O guia de movimento reduzido explica o que conta como movimento que vale remover.

css
@media (prefers-reduced-motion: reduce) {
  .hero,
  .hero::before,
  .sky::after {
    animation: none;
  }
}
Uma regra que interrompe todas as técnicas acima. Confira se o quadro que fica ainda parece certo.

Evite

  • Ciclos mais rápidos que cerca de 8 segundos em áreas grandes
  • Rotação de matiz em arco-íris pela página inteira
  • Movimento atrás de texto corrido que as pessoas precisam ler
  • Animações que continuam rodando com a aba ociosa por minutos seguidos

Faça

  • Movimento lento e ambiente dentro de uma família de cor
  • Movimento no hero, quietude no conteúdo
  • Um quadro parado e calmo para movimento reduzido
  • Teste em um notebook e um celular modestos, não só em um desktop rápido

Perguntas frequentes

É possível animar um gradiente CSS?

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

Qual é o jeito mais suave de animar um fundo em gradiente?

Animar transform ou opacity em uma camada de gradiente separada, porque os navegadores costumam tratá-las sem repintar.

Como animo as cores de um gradiente em CSS?

Registre cada cor com @property usando syntax: "<color>", use as propriedades no gradiente e mude-as em @keyframes.

Gradientes animados deixam a página lenta?

Os pequenos raramente importam. Fundos animados grandes que repintam a cada quadro podem custar bateria e fluidez, então prefira transform ou opacity e meça com o DevTools.

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

Envolva uma regra animation: none em @media (prefers-reduced-motion: reduce) para que quem pede menos movimento veja um quadro parado.

Compartilhar este guia

Escrito pelo GradientlyConta verificada do Gradiently

A equipe por trás do Gradiently, uma ferramenta de design criada em torno dos Marks: gradientes vivos que fazem tudo o que você cria ter a sua cara.

Ver nosso perfil