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.

Moonbeam

Moonbeam

Cursor

Cursor

Rogue

Rogue

Editorially

Editorially

Editrix AI

Editrix AI

Pixel Perfect

Pixel Perfect

Algochurn

Algochurn

Aceternity UI

Aceternity UI

Tailwind Master Kit

Tailwind Master Kit

SmartBridge

SmartBridge

Renderwork Studio

Renderwork Studio

Creme Digital

Creme Digital

Golden Bells Academy

Golden Bells Academy

Invoker Labs

Invoker Labs

E Free Invoice

E Free Invoice

Installation

Install Dependencies

npm i svelte-motion clsx tailwind-merge

Add util file

src/lib/utils/cn.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
        
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}

Copy the source code

src/lib/components/ui/HeroParallax/HeroParallax.svelte
<script lang="ts">
	export let products: {
		title: string;
		link: string;
		thumbnail: string;
	}[];

	import { Motion, useTransform, useSpring, useViewportScroll } from 'svelte-motion';
	import ProductCard from './ProductCard.svelte';

	const firstRow = products.slice(0, 5);
	const secondRow = products.slice(5, 10);
	const thirdRow = products.slice(10, 15);
	let ref: HTMLDivElement | null = null;

	const { scrollYProgress } = useViewportScroll();

	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);
</script>

<div
	bind:this={ref}
	class="relative flex h-[300vh] flex-col self-auto overflow-hidden py-4 antialiased [perspective:1000px] [transform-style:preserve-3d]"
>
	<div class="relative left-0 top-0 mx-auto w-full max-w-7xl px-4 py-8 md:py-4">
		<h2 class="text-2xl font-bold dark:text-white md:text-7xl">
			The Ultimate <br /> development studio
		</h2>
		<p class="mt-8 max-w-2xl text-base dark:text-neutral-200 md:text-xl">
			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>
	<Motion
		let:motion
		style={{
			rotateX,
			rotateZ,
			translateY,
			opacity
		}}
	>
		<div use:motion>
			<Motion let:motion>
				<div use:motion class="mb-20 flex flex-row-reverse space-x-20 space-x-reverse">
					{#each firstRow as product (product.title)}
						<ProductCard {product} translate={translateX} />
					{/each}
				</div>
			</Motion>
			<Motion let:motion>
				<div use:motion class="mb-20 flex flex-row space-x-20">
					{#each secondRow as product (product.title)}
						<ProductCard {product} translate={translateXReverse} />
					{/each}
				</div>
			</Motion>
			<Motion let:motion>
				<div use:motion class="flex flex-row-reverse space-x-20 space-x-reverse">
					{#each thirdRow as product (product.title)}
						<ProductCard {product} translate={translateX} />
					{/each}
				</div>
			</Motion>
		</div>
	</Motion>
</div>
src/lib/components/ui/HeroParallax/ProductCard.svelte
<script lang="ts">
	import { Motion, MotionValue } from 'svelte-motion';

	export let product: {
		title: string;
		link: string;
		thumbnail: string;
	};
	export let translate: MotionValue<number>;
</script>

<Motion
	let:motion
	style={{
		x: translate
	}}
	whileHover={{
		y: -20
	}}
>
	<div use:motion class="group/product relative h-96 w-[30rem] flex-shrink-0">
		<a href={product.link} class="block group-hover/product:shadow-2xl">
			<img
				src={product.thumbnail}
				height="600"
				width="600"
				class="absolute inset-0 h-full w-full object-cover object-left-top"
				alt={product.title}
			/>
		</a>
		<div
			class="pointer-events-none absolute inset-0 h-full w-full bg-black opacity-0 group-hover/product:opacity-80"
		></div>
		<h2 class="absolute bottom-4 left-4 text-white opacity-0 group-hover/product:opacity-100">
			{product.title}
		</h2>
	</div>
</Motion>
src/lib/components/ui/HeroParallax/index.ts
import HeroParallax from './HeroParallax.svelte';
import ProductCard from './ProductCard.svelte';

export { HeroParallax, ProductCard };

Props

HeroParallax
Prop Type Description
products Array<{title: string, link: string, thumbnail: string}> An array of product objects.
ProductCard
Prop Type Description
product {title: string, link: string, thumbnail: string} An object representing a product.
translate MotionValue<number> A type of props