Infinite marquee is a common user interface feature that is often used to display scrolling text or images. It is a simple and effective way to grab a user's attention and convey important information.
In this blog, we will explore how to create an infinite marquee using JavaScript and the GSAP animation library. The code we will be using is as follows:
GSAP cdn:- here
HTML:
<div class="container">
<div class="marquee" wb-data="marquee" duration="20">
<div class="marquee-content">
<span>Yashraj Vaghela</span>
<span>Yashraj Vaghela</span>
<span>Yashraj Vaghela</span>
</div>
</div>
</div>
CSS:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
width: 100%;
}
.marquee {
width: 100%;
display: flex;
overflow: hidden;
white-space: nowrap;
gap: 1rem;
}
.marquee-content {
display: flex;
gap: 1rem;
}
.marquee-content span {
font-family: "Clash Display", sans-serif;
font-size: 20vw;
font-weight: 700;
}
JavaScript:
const init = () => {
const marquee = document.querySelector('[wb-data="marquee"]');
if (!marquee) {
return;
}
const duration = parseInt(marquee.getAttribute("duration"), 10) || 5;
console.log(duration);
const marqueeContent = document.querySelector(".marquee-content");
if (!marqueeContent) {
return;
}
const marqueeContentClone = marqueeContent.cloneNode(true);
marquee.append(marqueeContentClone);
let tween;
const playMarquee = () => {
let progress = tween ? tween.progress() : 0;
tween && tween.progress(0).kill();
const width = parseInt(
getComputedStyle(marqueeContent).getPropertyValue("width"),
10
);
const gap = parseInt(
getComputedStyle(marqueeContent).getPropertyValue("column-gap"),
10
);
const distanceToTranslate = -1 * (gap + width);
tween = gsap.fromTo(
marquee.children,
{ x: 0 },
{ x: distanceToTranslate, duration, ease: "none", repeat: -1 }
);
tween.progress(progress);
};
playMarquee();
function debounce(func) {
var timer;
return function (e) {
if (timer) clearTimeout(timer);
timer = setTimeout(
() => {
func();
},
500,
e
);
};
}
window.addEventListener("resize", debounce(playMarquee));
};
document.addEventListener("DOMContentLoaded", init);
Let's go over the code step by step:
- First, we select the marquee element using document.querySelector('[wb-data="marquee"]'). This selects the element with the wb-data attribute set to "marquee".
- We check if the marquee element exists. If it doesn't, we return from the function.
- We get the duration of the animation from the duration attribute of the marquee element. If the attribute is not set, we default to a duration of 5 seconds.
- We select the marquee content element using document.querySelector(".marquee-content").
- We check if the marquee content element exists. If it doesn't, we return from the function.
- We clone the marquee content element using marqueeContent.cloneNode(true) and append it to the marquee element using marquee.append(marqueeContentClone). This allows the content to loop seamlessly.
- We define a playMarquee function that animates the marquee content. This function first checks if there is already an animation in progress, and if there is, it stops it and resets the progress to 0. It then calculates the width of the marquee content element and the gap between columns, and calculates the distance to translate the content to achieve the infinite loop effect. Finally, it uses the GSAP library to animate the marquee content using gsap.fromTo.
- We call the playMarquee function to start the animation.
- We define a debounce function that limits the rate at which the playMarquee function is called. This helps improve performance and prevent unnecessary animation.
- We add an event listener to the window that listens for "resize" and calls Debounce(playMarquee) function every time the screen is resized.
NOTE:-
There are chances of text snapping based on your layout so please Adjust duration in HTML and the Font size based on your layout.
Top comments (1)
Good work bro. I have implement it with React