Como fazer animação infinita de fundo com CSS?

Olá Web Developer. Hoje veremos como criar uma animação infinita de fundo com CSS puro. Por ser infinita teremos que saber como cuidar para que o usuário não perceba quando a animação for reiniciada.

Animações CSS assim são ótimas, pois você tem controle programaticamente e são bem mais leves do que imagens ou vídeos. Obviamente que você pode colocar imagens nesta técnica, mas neste exemplo veremos como fazer sem nem precisar de imagens.

Esta técnica foi usada para as estrelas que aparecem de fundo ao finalizar um curso da TreinaWeb.

Tela do painel da TreinaWeb ao concluir um curso

Prévia do resultado:

Criando o Fundo do Céu

Para criar o céu vamos simplesmente criar uma <div>. Ela será um contêiner para que a gente coloque dentro os elementos que serão animados.

<div class="container" >

</div>

Em seguida vamos estilizar este elemento. Com o intuito de termos um exemplo mais simples, vou definir uma largura e altura para ele. Dessa forma nossa animação será menor, então não vamos precisar desenhar tantas estrelas para ter um bom efeito. Mas é claro que você pode fazer do tamanho que quiser.

Também vou adicionar um gradiente como fundo para simular a cor do céu. Teste com outras cores e outras formas de gradiente. Um gerador de gradientes muito bacana é o https://cssgradient.io/.

.container{
  width: 350px;
  height: 150px;
  background: linear-gradient(0, #120c56, #000000);
}

A primeira estrela no céu

Logo após a criação do céu vem a parte onde iniciaremos nossas estrelas. Você verá como é simples criá-las sem utilizar nenhuma imagem e sem lotar nosso HTML com tags. Basicamente iremos adicionar uma única <div>, que também vamos adicionar a classe stars.

<div class="container" >
    <div class="stars" ></div>
</div>

Pode ser difícil de acreditar no começo, mas este é basicamente todo o HTML que precisamos. Então vamos estilizar o novo elemento para a criação das estrelas.

.stars{
    width: 3px;
    height: 3px;
    border-radius: 50%;
}

O que fizemos aqui é muito simples: deixamos a nossa <div> com 3px de largura e altura, e utilizamos o border-radius para que ela fique arredondada, resultando em uma bolinha que será nossa estrela. Mas dessa forma nós não vamos enxergar nada no momento, porque ela não tem cor, é invisível.

É exatamente agora que entra o segredinho para criar várias estrelas com uma única <div>! A propriedade box-shadow nos permite criar várias sombras do elemento em qualquer posição e em qualquer cor. Então podemos utilizar essa propriedade para criar “clones” do nosso elemento na cor que quisermos.

.stars{
    width: 3px;
    height: 3px;
    border-radius: 50%;
    box-shadow: 50px 30px white,
    100px 80px white,
    80px 120px white,
    300px 20px white,
    250px 130px white,
    200px 50px white,
    150px 100px white,
    320px 100px white;
}

Cada sombra deve ser separada por vírgula. O primeiro valor é a posição horizontal, a segunda é a vertical e a terceira é a cor. Já que o nosso céu possui a dimensão de 350×150, atente-se para não criar as sombras fora do céu, ou elas não vão aparecer.

O tamanho das sombras sempre será do mesmo tamanho do elemento. Como criamos um elemento de 3px X 3px, este será o tamanho de todas as sombras.

É provável que você ache esta etapa bem cansativa e repetitiva. O melhor para criar as sombras é utilizar algum pré-processador de CSS como o Sass para automatizar isso. Por consequência bastará criar uma função para gerar as sombras, onde você pode passar as configurações de tamanho, cor, quantidade, posições e mandar ele gerar as posições aleatoriamente.

CSS - Sass
Curso de CSS - Sass
CONHEÇA O CURSO

Animando as Estrelas

Vamos iniciar a animação das nossas estrelas.

@keyframes anim-stars {
    from {
        transform: translateY(0px);
    }
    to {
        transform: translateY(-150px);
    }
}

Basicamente criamos uma animação que fará o valor de transform ir de translateY(0px) para translateY(-150px). Isso significa que o elemento que animarmos com isso irá subir 150px. Este é exatamente o valor da altura do nosso contêiner, e você já vai entender o motivo disso.

Para que a gente tenha a animação funcionando, vamos adicioná-la ao nosso elemento das estrelas.

.stars{
    ...
    animation: anim-stars 10s linear infinite;
}

Estamos chamando a nossa animação, ajustando-a para durar 10 segundos com uma velocidade constante (linear) e que vai repetir infinitamente (infinite).

O único problema com essa animação é que rapidamente percebemos onde acabam as estrelas e quando a animação é reiniciada. A fim de arrumar isso teremos o passo final.

Deixando a animação infinita

Para dar a ideia de animação infinita não podemos deixar as pessoas perceberem quando a animação é reiniciada. Para que a gente consiga esse resultado vamos precisar de uma cópia exata de nossas estrelas e posicioná-las mais abaixo das estrelas originais.

No momento em que as estrelas originais acabarem, a nossa cópia já vai entrar em cena, parecendo uma continuação. Caso ainda esteja um pouco confuso, vamos ver como vai ficar e você logo vai entender.

Com o intuito de ter uma cópia das nossas estrelas sem precisar criar outra <div>, vamos utilizar o pseudo-elemento ::after. Para que ele apareça mas sem conteúdo, vamos utilizar a propriedade content com o valor " ". Para deixá-lo de maneira idêntica à nossa <div>, vamos copiar todas as propriedades dela. Apenas vamos ignorar a propriedade animation. Isso porque o pseudo-elemento já será animado junto com a <div>.

.stars::after{
  content: " ";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  box-shadow: 50px 30px white,
    100px 80px white,
    80px 120px white,
    300px 20px white,
    250px 130px white,
    200px 50px white,
    150px 100px white,
    320px 100px white;
}

Dessa maneira nós teremos um pseudo-elemento com estrelas (sombras) nas exatas posições das estrelas que criamos anteriormente. Para termos essas estrelas mais abaixo vamos mudar sua posição. O primeiro passo para isso é colocar um position: relative na nossa <div>.

.stars{
    position: relative;
    width: 3px;
    height: 3px;
    ...
}

E agora no nosso pseudo-elemento vamos colocar um position: absolute para podermos movê-lo em relação à posição da <div>. Vamos colocar um top: 150px para que ele vá 150px para baixo. Este valor é por causa da altura do nosso céu.

.stars::after{
  content: " ";
  position: absolute;
  top: 150px;
  width: 3px;
  ...
}

Desse modo nós já teremos o resultado esperado. Lembre-se que a animação inteira possui 10 segundos. Você pode ficar o tempo que quiser e verá que a animação continua rodando sem parar e sem deixar claro quando ela foi reiniciada.

HTML5 e CSS3 - Desenvolvimento web Avançado
Curso de HTML5 e CSS3 - Desenvolvimento web Avançado
CONHEÇA O CURSO

Entendendo a Animação Infinita de Fundo

Para entender melhor como esse efeito funciona eu pintei as estrelas do pseudo-elemento de outra cor.

Veja que logo que as estrelas brancas (que são da nossa <div>) sobem, as estrelas do nosso pseudo-elemento já sobem juntas. Isso faz com que a gente não perceba onde termina e onde começa a animação.

O verdadeiro fim da animação é quando toda a nossa <div> sai de cena. Neste momento o nosso pseudo-elemento irá tomar exatamente a posição inicial da nossa <div>. Como a animação acaba nesse exato momento, ela é reiniciada. Dessa forma, a <div> volta para sua posição inicial, que era onde o pseudo-elemento estava.

Já que o pseudo-elemento e a <div> são idênticos, não há como percebermos que houve essa troca entre eles, o que disfarça a reinicialização da animação.

Você também pode ter notado agora que as estrelas estão aparecendo fora do céu. Isso foi apenas para mostrar como a animação funciona. Para evitar isso basta adicionar overflow: hidden na classe .container e as estrelas que estiverem fora não serão exibidas.

Melhorando a animação com Parallax

Parallax é um efeito utilizado para passar a ideia de profundidade. Já ensinei a fazer o efeito parallax aqui no blog utilizando apenas CSS.

Para fazer isso no nosso céu basta colocarmos uma nova <div> para termos uma nova camada de estrelas.

<div class="container" >
    <div class="stars" ></div>
    <div class="stars2" ></div>
</div>

Por fim iremos criar as estrelas no CSS da mesma forma. Para dar uma ideia de que são estrelas mais ao fundo, agora farei estrelas menores. Podemos reutilizar a animação, mas agora também farei uma pequena modificação: vou passar o tempo de 10 segundos para 20 segundos. Com as duas animações em tempos e tamanhos diferentes teremos o efeito de profundidade.

.stars2{
  position: relative;
  width: 1px;
  height: 1px;
  border-radius: 50%;
  box-shadow: 15px 15px white,
    125px 35px white,
    50px 80px white,
    10px 120px white,
    275px 90px white,
    230px 10px white,
    120px 130px white,
    300px 130px white,
    220px 115px white;
  animation: anim-stars 20s linear infinite;
}

.stars2::after{
  content: " ";
  position: absolute;
  top: 150px;
  width: 1px;
  height: 1px;
  border-radius: 50%;
  box-shadow: 15px 15px white,
    125px 35px white,
    50px 80px white,
    10px 120px white,
    275px 90px white,
    230px 10px white,
    120px 130px white,
    300px 130px white,
    220px 115px white;
}

Desenvolvedor Front-end Sênior
Formação: Desenvolvedor Front-end Sênior
HTML, CSS e JavaScript são a base de toda a web. Tudo o que você está vendo aqui agora depende deste tripé.Nesta formação aprenderemos Sass, Google Analytics, empacotar nossas aplicações com Webpack, criação de aplicações Desktop com Electron, UX/UI e uma introdução aos frameworks mais utilizados no mercado: Angular, React, Vue e Ember.
CONHEÇA A FORMAÇÃO
Deixe seu comentário

Graduado em Análise e Desenvolvimento de Sistemas, Pós-graduado em Projetos e Desenvolvimento de Aplicações Web e MBA em Machine Learning. Especializado em Front End e curte desenvolvimento de jogos.

© 2004 - 2019 TreinaWeb Tecnologia LTDA - CNPJ: 06.156.637/0001-58 Av. Paulista, 1765, Conj 71 e 72 - Bela Vista - São Paulo - SP - 01311-200