So I'm trying to do this vanilla text animation with JS and CSS but when I apply it to more that one text it work only on the fist one. I follow this tutorial: https://www.youtube.com/watch?v=GUEB9FogoP8&t=687s
It works but only on one text element. I saw the same animation on a portfolio of https://www.fromluke.com Which is even cleaner, but he used a different method.
Thanks for your tips!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="text-test.css">
</head>
<body>
<div >
<di >
<h1 >Hi,I'm</h1>
</di>
<h1 >Super Mario</h1>
</div>
<script src="app.js"></script>
</body>
</html>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family:'Outfit', sans-serif;
}
body {
background-color:white;
}
h1{
color:black;
font-size: 140px;
text-align:left;
font-weight: 500;
text-transform: uppercase;
overflow: hidden;
}
span{
opacity: 0;
transform: translateY(200px);
transition: all 0.8s ease;
display:inline-block;
}
span.fade{
opacity: 1;
transform: translateY(0px);
}
.space{
width:24px;
height: 5px;
position: relative;
}
.c-container {
max-width: 1920px;
margin-right: auto;
margin-left: auto;
padding-right: 4rem;
padding-left: 4rem;
}
const text = document.querySelector('.fancy');
const textString = text.textContent;
const splitText = textString.split("");
text.textContent = "";
for (let i=0; i < splitText.length; i ) {
if (splitText[i] === " ") {
text.innerHTML = "<span class='space'>" splitText[i] "</span>";
} else {
text.innerHTML = "<span>" splitText[i] "</span>";
}
}
let char = 0;
let timer = setInterval(onTick, 40);
function onTick() {
if (char < splitText.length) {
const span = text.querySelectorAll('span')[char];
span.classList.add('fade');
char ;
if (char === splitText.length) {
complete();
return
}
}
}
CodePudding user response:
If you use document.querySelector, JavaScript will return an array containing all elements that match the query. However, if you wish to perform an action on each element you've returned, you'll need to use the JavaScript foreach function.
In your case, JavaScript currently processes the first element of the returned array and stops afterways. To fix this, use:
const text = document.querySelector('.fancy');
text.forEach(item){
const textString = item.textContent;
const splitText = textString.split("");
item.textContent = "";
for (let i=0; i < splitText.length; i ) {
if (splitText[i] === " ") {
item.innerHTML = "<span class='space'>" splitText[i] "</span>";
} else {
item.innerHTML = "<span>" splitText[i] "</span>";
}
}
As you can see, I've moved the logic you're using to animate the item to within the forEach function.
The document.querySelector('.fancy');
will return an array containing elements that match the query.
The forEach function which is called on text
- the array containing the elements that matched the quesry of document.querySelector
- will use item
to refer to the iterated element.
CodePudding user response:
I noticed an issue in your script, you're only selecting one element instead you need to use this :
querySelectorAll('.fade')
const allTextArray = document.querySelectorAll('.fancy');
for (let j = 0; j < allTextArray.length; j ) {
let text = allTextArray[j]
const textString = text.textContent;
const splitText = textString.split("");
text.textContent = "";
for (let i = 0; i < splitText.length; i ) {
if (splitText[i] === " ") {
text.innerHTML = "<span class='space'>" splitText[i] "</span>";
} else {
text.innerHTML = "<span>" splitText[i] "</span>";
}
}
let char = 0;
let timer = setInterval(onTick, 400);
function onTick() {
if (char < splitText.length) {
const span = text.querySelectorAll('span')[char];
span.classList.add('fade');
char ;
if (char === splitText.length) {
complete();
return
}
}
}
}