Hero Parallax
A scroll effect with rotation, translation and opacity animations.
The Ultimate
development studio
We build beautiful products with the latest technologies and frameworks. We are a team of passionate developers and designers that love to build amazing products.
Installation
Install dependencies
npm i motion clsx tailwind-merge
Add util file
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Copy the source code
components/ui/hero-parallax.tsx
"use client";
import React from "react";
import {
motion,
useScroll,
useTransform,
useSpring,
MotionValue,
} from "motion/react";
import Image from "next/image";
import Link from "next/link";
export const HeroParallax = ({
products,
}: {
products: {
title: string;
link: string;
thumbnail: string;
}[];
}) => {
const firstRow = products.slice(0, 5);
const secondRow = products.slice(5, 10);
const thirdRow = products.slice(10, 15);
const ref = React.useRef(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start start", "end start"],
});
const springConfig = { stiffness: 300, damping: 30, bounce: 100 };
const translateX = useSpring(
useTransform(scrollYProgress, [0, 1], [0, 1000]),
springConfig
);
const translateXReverse = useSpring(
useTransform(scrollYProgress, [0, 1], [0, -1000]),
springConfig
);
const rotateX = useSpring(
useTransform(scrollYProgress, [0, 0.2], [15, 0]),
springConfig
);
const opacity = useSpring(
useTransform(scrollYProgress, [0, 0.2], [0.2, 1]),
springConfig
);
const rotateZ = useSpring(
useTransform(scrollYProgress, [0, 0.2], [20, 0]),
springConfig
);
const translateY = useSpring(
useTransform(scrollYProgress, [0, 0.2], [-700, 500]),
springConfig
);
return (
<div
ref={ref}
className="h-[300vh] py-40 overflow-hidden antialiased relative flex flex-col self-auto [perspective:1000px] [transform-style:preserve-3d]"
>
<Header />
<motion.div
style={{
rotateX,
rotateZ,
translateY,
opacity,
}}
className=""
>
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20 mb-20">
{firstRow.map((product) => (
<ProductCard
product={product}
translate={translateX}
key={product.title}
/>
))}
</motion.div>
<motion.div className="flex flex-row mb-20 space-x-20 ">
{secondRow.map((product) => (
<ProductCard
product={product}
translate={translateXReverse}
key={product.title}
/>
))}
</motion.div>
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20">
{thirdRow.map((product) => (
<ProductCard
product={product}
translate={translateX}
key={product.title}
/>
))}
</motion.div>
</motion.div>
</div>
);
};
export const Header = () => {
return (
<div className="max-w-7xl relative mx-auto py-20 md:py-40 px-4 w-full left-0 top-0">
<h1 className="text-2xl md:text-7xl font-bold dark:text-white">
The Ultimate <br /> development studio
</h1>
<p className="max-w-2xl text-base md:text-xl mt-8 dark:text-neutral-200">
We build beautiful products with the latest technologies and frameworks.
We are a team of passionate developers and designers that love to build
amazing products.
</p>
</div>
);
};
export const ProductCard = ({
product,
translate,
}: {
product: {
title: string;
link: string;
thumbnail: string;
};
translate: MotionValue<number>;
}) => {
return (
<motion.div
style={{
x: translate,
}}
whileHover={{
y: -20,
}}
key={product.title}
className="group/product h-96 w-[30rem] relative shrink-0"
>
<Link
href={product.link}
className="block group-hover/product:shadow-2xl "
>
<Image
src={product.thumbnail}
height="600"
width="600"
className="object-cover object-left-top absolute h-full w-full inset-0"
alt={product.title}
/>
</Link>
<div className="absolute inset-0 h-full w-full opacity-0 group-hover/product:opacity-80 bg-black pointer-events-none"></div>
<h2 className="absolute bottom-4 left-4 opacity-0 group-hover/product:opacity-100 text-white">
{product.title}
</h2>
</motion.div>
);
};
Props
HeroParallax
Prop | Type | Description |
---|---|---|
products | Array | An array of product objects. Each object should have a title (string), link (string), and thumbnail (string). |
ProductCard
Prop | Type | Description |
---|---|---|
product | Object | An object representing a product. It should have a title (string), link (string), and thumbnail (string). |
translate | MotionValue<number> | A Framer Motion value representing the translation of the product card on the x-axis. |
Build websites faster and 10x better than your competitors with Aceternity UI Pro
With the best in class components and templates, stand out from the crowd and get more attention to your website. Trusted by founders and entrepreneurs from all over the world.
Excellent communication and professionalism from the start and
throughout. Happily and calmly accepted and entertained a few additional
out-of-scope requests as well. Good open-...
Henrik Söderlund
Former CTO at Creme Digital