Initializing the project
Let's start the project by creating a Next.js application. We can do that by running npx create-next-app@latest client
inside of a terminal.
- The background image is added inside a new
/public/images
. - You can find the one I used here.
Adding the HTML and CSS
We can delete everything in the page.js
, global.css
and page.module.css
and add our own HTML and CSS, to start with a nice blank application.
- Let's also add
margin: 0px
on the body in the globals.css
to make everything clean.
Setting up the page.js
component
2
import Image from 'next/image'
3
import styles from './page.module.css'
4
import { useRef } from 'react';
6
export default function Home() {
8
const firstText = useRef(null);
9
const secondText = useRef(null);
10
const slider = useRef(null);
13
<main className={styles.main}>
15
src="/images/background.jpg"
19
<div className={styles.sliderContainer}>
20
<div ref={slider} className={styles.slider}>
21
<p ref={firstText}>Freelance Developer -</p>
22
<p ref={secondText}>Freelance Developer -</p>
Couple of important things to note about the code above:
- The second
p
is set in position absolute
with a left: 100%
so that it's perfectly placed at the right of the first. white-space: nowrap
so the text overflows outside the window.
We should have something like this:
Creating the infinite move
To move the texts, we'll basically use requestAnimationFrame
and at each frame we will move the texts by 0.1% to the right.
We will also use the GSAP Library to set xPercent value of the texts.
5
gsap.set(secondText.current, {left: secondText.current.getBoundingClientRect().width})
6
requestAnimationFrame(animate);
13
gsap.set(firstText.current, {xPercent: xPercent})
14
gsap.set(secondText.current, {xPercent: xPercent})
15
requestAnimationFrame(animate);
- Initially, the xPercent is set at -100%, and is gradually incremented to 0%, when it reaches 0%, it gets reset back to -100%.
We should have something like this:
Adding scroll interaction
With the scroll, we can now change direction depending on the scroll direction.
We can also add an extra move on the texts when scrolling to make everything more responsive to the scroll.
To do that, we will use the ScrollTrigger library from GSAP.
5
gsap.registerPlugin(ScrollTrigger);
6
gsap.to(slider.current, {
8
trigger: document.documentElement,
11
end: window.innerHeight,
12
onUpdate: e => direction = e.direction * -1
16
requestAnimationFrame(animate);
19
const animate = () => {
23
else if(xPercent > 0){
26
gsap.set(firstText.current, {xPercent: xPercent})
27
gsap.set(secondText.current, {xPercent: xPercent})
28
requestAnimationFrame(animate);
29
xPercent += 0.1 * direction;
Couple notes about the code above:
- ScrollTrigger allows us to set translate the texts by 500px depending on the progress of the start(0) and the end(window.innerHeight).
- ScrollTrigger also allows us to easly read the direction of the scroll.
And here we should have the final animation:
Wrapping up
That was it for this animation! Very interesting to know how to move text on an infinite basis, it's actually quite easy when leveraging CSS values with percentage. It's a good animation to know and it's quite a popular one as well!
Hope you learned a lot :)
-Oli