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.
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 350x150, 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.
Curso CSS - Sass
Conhecer o cursoAnimando 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.
Curso Scrum - Planejamento e Desenvolvimento Ágeis
Conhecer o cursoEntendendo 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;
}