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 |
|
2 |
|
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 |
|
2 |
|
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 span
s 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 span
s 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.
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!