# Fundos com gradiente animado em CSS, do jeito certo

[Canonical HTML page](https://gradiently.design/pt-br/guide/css-animated-gradient)

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.

## The short version

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

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.

- Quadro 1: crepúsculo: `linear-gradient(120deg, #1e1b4b, #7c3aed 45%, #f472b6)`
- Quadro 2: mais tarde: `linear-gradient(160deg, #1e1b4b, #6d28d9 35%, #fb7185)`
- Quadro 3: brasa: `linear-gradient(200deg, #1e1b4b, #4c1d95 30%, #fb923c)`

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](https://gradiently.design/pt-br/guide/animated-gradient-background). 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](https://caniuse.com/mdn-css_at-rules_property) 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.

- Início: violeta a rosa: `linear-gradient(120deg, #7c3aed, #f472b6)`
- Fim: ciano a laranja: `linear-gradient(200deg, #0891b2, #fb923c)`

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](https://gradiently.design/pt-br/guide/css-mesh-gradient), girar uma [borda cônica](https://gradiently.design/pt-br/guide/css-gradient-border) 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écnica | Trabalho do navegador por quadro | Melhor para |
| --- | --- | --- |
| Mover o `background-position` | Repintura | Elementos pequenos, botões, texto |
| Cores e ângulos com `@property` | Repintura | Mudanças precisas de cor, bordas giratórias |
| `transform` em uma camada | Em geral só composição | Fundos grandes, de tela cheia |
| Fade cruzado com `opacity` | Em geral só composição | Mudanç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](https://gradiently.design/pt-br/guide/css-gradient-performance) 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](https://gradiently.design/pt-br/guide/reduced-motion) 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

## FAQ

### É 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.
