I used to be apprehensive about parallax-focused designs. Despite finding them visually appealing, I thought it was challenging to make all the elements work together. However, last weekend, I decided to give it another try, this time using Next.js and GSAP.
I was amazed at how effortlessly everything came together. Adapting the design for mobile view was still challenging, requiring me to create a different set of clouds, but everything else remained the same.
What is GSAP?
GSAP (or, Greensock Animation Provider) is a JavaScript library that enables developers to create high performing animated websites by providing configuration objects, tweens and timelines to help create seamless animations.
Tweens: A tween is an animation property setter that takes the object that you want to animate, a duration and the property that you would want to animate through (eg. axes)
Timelines: A timeline is a sequencing tool that will help you sequence multiple tweens, and lets you position animation and create an entire sequence of beautiful animation.
How do you build a Parallax Powered Page in under 5 minutes?
Step 1 :
Step 2:
Create a Design in Figma. To create a captivating Parallax, you would need multiple components playing our simultaneously, and it’s best to have a design in mind before going ahead. The Pen tool in Figma will easily help you craft basic designs (like the ones I made above). Or, you could simply reuse the images I have created (GitHub link shared at the end).
Import the images into your NextJs component and layer then with position: absolute.
const parallaxCloudBackgroundStyles = 'z-10 absolute bottom-[0vw] w-[100vw]';
const parallaxCloudForegroundStyles = 'z-30 absolute bottom-[0vw] w-[100vw]';
const parallaxCloudTopLayerStyles = 'z-30 absolute bottom-[-5vw] w-[100vw]';
const parallaxStarStyles = 'absolute top-0 w-[100vw]';
const parallaxSunStyles = 'z-0 absolute top-[30%] left-[35%] right-[35%] w-[30%]';
const parallaxFlightStyles = 'z-20 rotate-45 absolute bottom-[-15%] left-[5%] w-[30vw]';
<img ref= {sun} src="./img/Sun.png" className={parallaxSunStyles}/>
<img ref= {cloudlayer1} src="./img/Wave L1.png" className = { parallaxCloudBackgroundStyles}/>
<img ref= {flight}src="./img/Designer.png" className = {parallaxFlightStyles}/>
<img ref= {cloudlayer2}src="./img/Wave L2.png" className = { parallaxCloudForegroundStyles }/>
<img ref= {cloudlayer3} src="./img/Wave L3.png" className = { parallaxCloudForegroundStyles }/>
<img ref= {cloudlayer4} src="./img/Wave L4.png" className = { parallaxCloudTopLayerStyles }/>
<img ref= {starrySky} src="./img/Starry Sky.png" className = {parallaxStarStyles}/>
What is z-index?
In web design, we have something similar called z-index. It helps us control the order in which elements (like images, buttons, or text) appear on a webpage.
Tailwind CSS provides a set of predefined z-index classes that you can apply to your elements. These classes range from z-0 (which sets the z-index to 0) to z-50 (which sets the z-index to 50). In the code above we have used z-indexes to layer our components. The bottom layer should be z-0, increasing as you move to the top.
Step 3: Create Refs for each element.
You would need to create Refs for each element and attach the ref to the element. This would help us control the animation for each layer.
const parallaxRef = useRef(null);
const cloudlayer1 = useRef(null);
const cloudlayer2 = useRef(null);
const cloudlayer3 = useRef(null);
const cloudlayer4 = useRef(null);
const flight = useRef(null);
const sun = useRef(null);
const starrySky = useRef(null);
STEP 4: Add all animation sequences in your timeline
It is time to unlock the power of GSAP.
Setting Up GSAP Context:
You start by creating a GSAP context using gsap.context(() => { ... })
. The context allows you to define animations and plugins within a specific scope.
Registering the ScrollTrigger Plugin:
You register the ScrollTrigger plugin using gsap.registerPlugin(ScrollTrigger)
. The ScrollTrigger plugin is essential for creating animations based on scroll position.
Creating a Timeline:
Next, you create a timeline using gsap.timeline({ ... })
. A timeline is like a container for your animations. It lets you sequence and control multiple animations together. The defaults
object specifies default properties for all animations within this timeline (in this case, a duration of 1 second).
ScrollTrigger Configuration:
You set up the scrollTrigger
for your timeline:
-
trigger: The element that triggers the animation (in this case,
parallaxRef.current
). - start: The position of the trigger element when the animation starts (here, “top top” means when the top of the trigger element reaches the top of the viewport).
- end: The position of the trigger element when the animation ends (here, “5000 bottom” means when the bottom of the trigger element reaches 5000 pixels from the top of the viewport).
- scrub: Enables smooth scrubbing (changes animation progress as you scroll).
- pin: Pins the trigger element during the animation.
- onUpdate: A callback function that runs whenever the scroll position updates. In your case, it adjusts the background based on scroll progress.
useEffect(() => {
let ctx = gsap.context(() => {
gsap.registerPlugin(ScrollTrigger);
var timeline = gsap.timeline({
defaults: { duration: 1},
scrollTrigger: {
trigger: parallaxRef.current,
start: "top top",
end: "5000 bottom",
scrub: true,
pin: true,
onUpdate: (self) => {
setBackground(Math.ceil(self.progress * 100 + 30))
console.log(Math.ceil(self.progress * 100))
},
},
});
});
});
STEP 5: Animate
Animating Elements:
Inside the timeline, you define animations:
timeline.to(flight.current, { y: "-=1500", x: "+=1500" }, 0)
: This animates the flight element by moving it up (y: "-=1500"
) and diagonally (x: "+=1500"
).
You’re starting with a zero offset (the last argument is 0), which means this animation starts immediately.
You can animate other elements similarly. A tip here would be to add a good mix of both positive and negative final offset values to get a better effect.
timeline.to(
flight.current,
{
y: "-=1500",
x: "+=1500"
},
0
);
timeline.to(
sun.current,
{
y: "-=400"
},
0
);
timeline.to(
starrySky.current,
{
y: "-=150"
},
0
);
STEP 5: RUN your website
npm run dev
— See your code in action
Find the working code here: Visit Github.com/abhirupa-tech
Want to get on a 1:1 call? Click here to connect with me
Happy Coding!
Please leave a feedback
I hope you found this blog helpful! Your feedback is invaluable to me, so please leave your thoughts and suggestions in the comments below.
Feel free to connect with me on LinkedIn for more insights and updates. Let's stay connected and continue to learn and grow together!
Top comments (0)