<h1>Scroll down luv</h1>
<div class="marquee" data-reversed="false">
<span>Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
</div>
<div class="marquee" data-reversed="true">
<span>Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
</div>
<div class="marquee" data-reversed="false">
<span>Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
<span aria-hidden="true">Oi, oi!</span>
</div>
body {
padding: 25vh 0 50vh 0;
background: #222;
scroll-behavior: smooth;
font: 600 8vw/1 "Inter", sans-serif;
}
h1 {
color: #777;
display: block;
font-size: 1.5rem;
padding: 0 0 35vh 0;
text-align: center;
text-transform: uppercase;
}
.marquee {
display: flex;
padding: 15px 0;
margin: 20px 0;
white-space: nowrap;
color: #DDD;
justify-content: flex-end;
background: #111;
&[data-reversed="true"] {
justify-content: flex-start;
}
span {
display: block;
padding: 0 1ch;
}
}
View Compiled
gsap.registerPlugin(ScrollTrigger);
let direction = 1;
const duration = 8;
const marquees = document.querySelectorAll(".marquee");
const tl = gsap.timeline({
repeat: -1,
yoyo: false,
onReverseComplete() {
this.totalTime(this.rawTime() + this.duration() * 10); // otherwise when the playhead gets back to the beginning, it'd stop. So push the playhead forward 10 iterations (it could be any number)
}
});
marquees.forEach(marquee => {
// This works beacause all the elements inside the marquee wrapper are exactly the same
tl.to(marquee.querySelectorAll("span"), {
xPercent: marquee.dataset.reversed === "true" ? -100 : 100,
repeat: 0,
ease: "linear",
duration: duration
}, "<");
});
let scroll = ScrollTrigger.create({
onUpdate(self) {
// Update the direction of the animation based on the direction of scroll
if (self.direction !== direction) {
direction *= -1;
}
// Update the animation speed (duration) based on the scroll speed
tl.timeScale(duration * self.getVelocity() / 500);
// Go back to the default duration
gsap.to(tl, {timeScale: direction});
}
});
View Compiled