Code
app/page.tsx
1import ZoomParallaxHero from "@/components/zoom-parallax-hero";
2
3const HomePage = () => {
4 return (
5 <ZoomParallaxHero />
6 );
7}
8
9export default HomePage;
Installation
Initialized a project and installed the necessary dependencies to use this component.
1. Initialize a new Next.js project:
npx create-next-app@latest my-app
2. Install Framer Motion
npm install framer-motion
Add Parallax Zoom Component
src/components/zoom-parallax-hero.tsx
1"use client"
2
3import { motion, useScroll, useTransform } from 'framer-motion';
4import { fadeSlideRight, fadeSlideLeft, fadeUp, fadeIn } from '@/anim';
5import { useRef } from 'react';
6
7
8const ZoomParallaxHero = () => {
9 const container = useRef(null);
10 const { scrollYProgress } = useScroll({
11 target: container,
12 offset: ['start start', 'end end']
13 })
14
15 const moveRight = useTransform(scrollYProgress, [0, 1], [0, 300]);
16 const moveLeft = useTransform(scrollYProgress, [0, 1], [0, -300]);
17
18 return (
19 <div ref={container} className="h-[300vh] relative bg-white text-black">
20 <div className="sticky overflow-hidden top-0 h-screen flex flex-col items-center justify-center">
21 <div className=' lg:px-10 2xl:px-20 pt-16 md:pt-20 md:pb-16 w-full flex flex-col justify-between h-[68%] md:h-full'>
22 <motion.div
23 style={{ x: moveRight }}
24 className=' w-full flex items-center justify-center md:justify-start md:px-20'
25 variants={fadeSlideRight}
26 initial="hidden"
27 animate="visible"
28 >
29 <motion.h1
30 className=' font-cabinetGrotesk text-7xl md:text-9xl xl:text-[12rem] font-bold uppercase'
31 variants={fadeIn}
32 initial="hidden"
33 animate="visible"
34 transition={{ delay: 0.2 }}
35 >Astrae</motion.h1>
36 </motion.div>
37 <motion.div
38 className=' hidden xl:flex w-full items-center justify-between'
39 variants={fadeUp}
40 initial="hidden"
41 animate="visible"
42 transition={{ delay: 0.4 }}
43 >
44 <span className='uppercase font-medium md:text-base 2xl:text-lg'>
45 A Creative
46 <span className=' font-semibold'>
47 Ecommerce Studio
48 </span>
49 </span>
50 <span className='uppercase font-medium md:text-base 2xl:text-lg'>
51 Setting Brands
52 <span className='font-semibold'>
53 In Motion
54 </span>
55 </span>
56 </motion.div>
57 <span>
58
59 <motion.div
60 style={{ x: moveLeft }}
61 className=' w-full flex items-center justify-center md:justify-end md:px-20'
62 variants={fadeSlideLeft}
63 initial="hidden"
64 animate="visible"
65 transition={{ delay: 0.6 }}
66 >
67 <motion.h1
68 className=' font-cabinetGrotesk text-7xl md:text-9xl xl:text-[12rem] font-bold uppercase'
69 variants={fadeIn}
70 initial="hidden"
71 animate="visible"
72 transition={{ delay: 0.8 }}
73 >Studios</motion.h1>
74 </motion.div>
75
76 <motion.div
77 className=' md:hidden flex flex-col w-full items-center'
78 variants={fadeUp}
79 initial="hidden"
80 animate="visible"
81 transition={{ delay: 0.4 }}
82 >
83 <span className=' uppercase font-medium md:text-base 2xl:text-lg'>
84 A Creative <span className=' font-semibold'>Ecommerce Studio</span>
85 </span>
86 <span className=' uppercase font-medium md:text-base 2xl:text-lg'>
87 Setting Brands <span className=' font-semibold'>In Motion</span>
88 </span>
89 </motion.div>
90 </span>
91
92 </div>
93 <motion.div
94 style={{ scale: useTransform(scrollYProgress, [0, 1], [1, 3]) }}
95 className="w-full h-full top-0 absolute flex items-center justify-center"
96 variants={fadeIn}
97 initial="hidden"
98 animate="visible"
99 transition={{ delay: 1 }}
100 >
101 <div
102 className={`
103 relative object-cover w-[90vw] xl:w-[40rem]
104 2xl:w-[52rem] h-auto aspect-square sm:aspect-video md:aspect-video`
105 }>
106 <video
107 autoPlay
108 loop
109 muted
110 playsInline
111 preload="auto"
112 className="object-cover w-full h-full"
113 >
114 <source src="/assets/showcase-2.mp4" type="video/mp4" />
115 Your browser does not support the video tag.
116 </video>
117 </div>
118 </motion.div>
119 </div>
120 </div>
121 )
122}
123
124export default ZoomParallaxHero;
Add Animations
src/anim/index.ts
1import { Variants } from "framer-motion";
2
3export const fadeSlideRight: Variants = {
4 hidden: { opacity: 0, x: -80 },
5 visible: { opacity: 1, x: 0, transition: { duration: 0.8, ease: "easeOut" } },
6};
7
8export const fadeSlideLeft: Variants = {
9 hidden: { opacity: 0, x: 80 },
10 visible: { opacity: 1, x: 0, transition: { duration: 0.8, ease: "easeOut" } },
11};
12
13export const fadeUp: Variants = {
14 hidden: { opacity: 0, y: 40 },
15 visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: "easeOut" } },
16};
17
18export const fadeIn: Variants = {
19 hidden: { opacity: 0 },
20 visible: { opacity: 1, transition: { duration: 1, ease: "easeOut" } },
21};
Add Global Styles
src/globals.css
1@import "tailwindcss";
2
3:root {
4 --background: #ffffff;
5 --foreground: #000000;
6}
7
8@theme inline {
9 --color-background: var(--background);
10 --color-foreground: var(--foreground);
11 --font-inter: var(--font-inter);
12 --font-cabinetGrotesk: var(--font-cabinetGrotesk);
13}
14
15@media (prefers-color-scheme: dark) {
16 :root {
17 --background: #000000;
18 --foreground: #ededed;
19 }
20}
21
22body {
23 background: var(--background);
24 color: var(--foreground);
25 font-family: Arial, Helvetica, sans-serif;
26}
27
28
29/* Scrollbar */
30
31/* Firefox */
32* {
33 scrollbar-width: none;
34}
35/* Chrome, Edge, and Safari */
36*::-webkit-scrollbar {
37 display: none;
38}
39/* End Scrollbar */