Crie uma animação de texto piscando infinitamente com CSS e um toque de JavaScript

Neste novo tutorial, aprenderemos como criar um efeito de texto piscando/piscando infinito com animações CSS e um pouco de JavaScript. Especificamente, as partes do texto selecionadas mudarão de cor após um determinado período. Depois disso, a animação será reinicializada.

Nosso efeito de texto

Aqui está o que vamos criar. É um ótimo complemento para um portfólio ou página de destino de uma empresa, para destacar marcas, nomes, lugares e assim por diante.

1. Comece com a marcação HTML

Dentro de um contêiner, definiremos um elemento wrapper que conterá algum texto de marcas conhecidas, como este:

1
 class="container">
2
   class="blinking-wrapper">
3
    Accenture,
4
    Amazon
5
    Apple,
6
    Astrazeneca,
7
    Citigroup,
8
    Coca-Cola Co,
9
    China Merchants Bank,
10
    Disney
11
    Google,
12
    ...
13
  
14

Para cada marca (pedaço de texto) que queremos animar, vamos envolvê-la dentro de um span elemento e dar-lhe o data-number atributo. O valor do atributo personalizado determinará a ordem da animação. Quanto menor o número, mais cedo a animação será executada. Dito isto, o elemento com o data-number="1" o valor do atributo será animado primeiro, depois isso com o data-number="2" valor do atributo, etc.

Aqui está o esqueleto de marcação necessário:

1
 class="container">
2
   class="blinking-wrapper">
3
    Accenture,
4
    Amazon
5
    Apple,
6
    Astrazeneca,
7
    Citigroup,
8
     data-number="1">Coca-Cola Co,
9
    China Merchants Bank,
10
    Disney
11
    Google,
12
    IBM,
13
     data-number="2">Intel,
14
    JPMorgan Chase,
15
    Mastercard,
16
    McDonalds,
17
    Meta,
18
    NASA,
19
     data-number="4">Nestle SA,
20
    Netflix,
21
    Nike,
22
    ...
23
  
24

2. Adicione o CSS

O CSS será bem básico. Tudo o que precisamos é aplicar uma animação CSS ao spans que mudarão sua cor de branco para um tom de nossa escolha. Mas observe uma coisa aqui: as animações serão executadas sequencialmente quando a página for carregada. Nesse ponto, adicionaremos o blinking class para o wrapper e dar spans atrasos apropriados.

No seu caso, dependendo do layout da página, você pode querer iniciar o efeito piscante quando o .blinking-wrapper elemento aparece.

Aqui estão todos os estilos:

1
/*CUSTOM VARIABLES HERE*/
2

3
.container {
4
  max-width: 1600px;
5
  padding: 0 15px;
6
  margin: 0 auto;
7
}
8

9
.blinking-wrapper {
10
  font-size: 50px;
11
}
12

13
.blinking-wrapper.blinking [data-number] {
14
  animation: changeColor 1.5s var(--delay, 0s);
15
}
16

17
@keyframes changeColor {
18
  to {
19
    color: var(--green);
20
  }
21
}
22

23
@media (max-width: 600px) {
24
  .blinking-wrapper {
25
    font-size: 25px;
26
  }
27
}

3. Aplique o JavaScript

Como mencionado acima, além de adicionar o blinking classe ao elemento wrapper quando a página for carregada, atribuiremos atrasos apropriados para cada span para determinar quando a animação piscante começará. O primeiro elemento não terá nenhum atraso. Todos os outros serão acionados assim que a animação do elemento animado anterior terminar.

Os atrasos geradosOs atrasos geradosOs atrasos gerados

Claro, você pode definir os atrasos manualmente ou ajustar os tempos conforme desejar.

Aqui está o código JavaScript necessário:

1
const blinkingWrapper = document.querySelector(".blinking-wrapper");
2
const animatedEls = blinkingWrapper.querySelectorAll("[data-number]");
3
const TOGGLE_CLASS = "blinking";
4
const BASE_DELAY = 1.5;
5

6
window.addEventListener("load", function () {
7
  blinkingWrapper.classList.add(TOGGLE_CLASS);
8
  animatedEls.forEach(function (el, index) {
9
    if (index != 0) {
10
      const delay = BASE_DELAY * el.dataset.number - BASE_DELAY;
11
      el.style.setProperty("--delay", `${delay}s`);
12
    }
13
  });
14
});

Repetir animações

Com este código implementado, nossas animações serão reproduzidas conforme o esperado pela primeira vez. Mas e se quisermos reproduzi-los em sequência (mantendo os atrasos desejados) infinitamente? Apenas usando o infinite palavra-chave para a contagem de iterações de animação não funcionará.

Nesse caso, esperaremos que todas as animações terminem antes de reinicializá-las usando o animationend evento do último elemento animado – aquele com o maior data-number. Uma maneira rápida de descobrir qual elemento deve ser esse é fornecer manualmente um ID/classe exclusivo. Alternativamente, podemos escrever algum código para recuperar o maior número de todos os data-number valores de atributos como abaixo:

1
...
2

3
function getMaxNumber() {
4
  const numbers = Array.from(animatedEls).map(function (el) {
5
    return el.dataset.number;
6
  });
7
  return Math.max(...numbers);
8
}

A seguir, direcionaremos o elemento desejado e ouviremos seu animationend evento.

1
...
2

3
blinkingWrapper
4
  .querySelector(`[data-number="${getMaxNumber()}"]`)
5
  .addEventListener("animationend", function () {
6
    //stuff here

7
  });

Dentro dele, faremos três coisas:

  • Remova o blinking classe do elemento wrapper.
  • Force um refluxo para esse elemento calculando sua altura ou qualquer coisa que o faça refluir sem retornar nada.
  • Adicione novamente o blinking classe para isso.

Dessa forma, as animações CSS serão retomadas com os atrasos em vigor cada vez que o grupo anterior terminar. Se não causarmos um refluxo, nossa animação não será reiniciada. Você pode testar removendo a ação de refluxo.

Aqui está o código JavaScript necessário:

1
...
2

3
blinkingWrapper
4
  .querySelector(`[data-number="${getMaxNumber()}"]`)
5
  .addEventListener("animationend", function () {
6
    blinkingWrapper.classList.remove(TOGGLE_CLASS);
7
    void blinkingWrapper.offsetHeight;
8
    blinkingWrapper.classList.add(TOGGLE_CLASS);
9
  });

Uma implementação alternativa, em vez de forçar um refluxo que pode ser caro dependendo de seus layouts, é anexar a classe ao wrapper após o menor atraso possível como este – dando um atraso zero, deixaremos o navegador decidir o menor atraso tempo:

1
...
2

3
blinkingWrapper
4
  .querySelector(`[data-number="${getMaxNumber()}"]`)
5
  .addEventListener("animationend", function () {
6
    blinkingWrapper.classList.remove(TOGGLE_CLASS);
7
    setTimeout(function () {
8
      blinkingWrapper.classList.add(TOGGLE_CLASS);
9
    }, 0);
10
  });

Além desses métodos discutidos aqui, existem outros também. Sinta-se livre para deixe-nos saber em X ou no comentários de demonstração se você usou qualquer outro para realizar algo semelhante!

Conclusão

Neste tutorial, conseguimos construir um efeito CSS piscante infinito com animações surpreendentes graças ao animationend evento. Este tipo de efeito é útil se você deseja destacar partes específicas do texto, como seus projetos mais recentes, principais clientes, principais habilidades, etc.

Aqui está novamente nosso efeito:

Como sempre, muito obrigado pela leitura!



Deixe uma resposta