Image Pile
ImagePile shuffles and layers images dynamically, creating a stylish, ever-changing visual effect. Built with React, Next.js, Framer Motion, and Tailwind CSS, itβs perfect for portfolios, galleries, and landing pages. Add motion and personality to your UI effortlessly! ππ¨
Preview
Follow below steps ππ»
Install dependencies
1npm i framer-motion
Component
Create a file image-pile.tsx in your components folder and paste this code
1'use client';23import React, { useEffect, useState } from 'react';4import Image from 'next/image';5import { motion } from 'framer-motion';67const ImagePile = ({ images, speed = 2 }: { images: string[]; speed?: number }) => {8const [topIndex, setTopIndex] = useState(0);910useEffect(() => {11const id = setInterval(() => {12setTopIndex((prevIndex) => (prevIndex + 1) % images.length);13}, speed * 1000);1415return () => {16clearInterval(id);17};18}, [images.length]);1920return (21<div className="relative h-[200px] sm:h-[260px] md:h-[390px] lg:h-[450px] xl:h-[500px] w-[310px] sm:w-[500px] md:w-[725px] lg:w-[900px] xl:w-[1200px] overflow-visible">22{images.map((image, i) => {23const key = `stacked-card-${i}`;24const isTop = topIndex === i;25const secondTopIndex = (topIndex + 2) % images.length;26const zIndex = isTop ? 100 : secondTopIndex ? 99 : images.length - i;27const y: number = Math.random() * 20;28const x: number = Math.random() * 20;29const rotation = i * (Math.random() * 1 + 2) - 2;3031return (32<motion.div33key={key}34className="absolute w-full h-full"35style={{36zIndex,37transformOrigin: 'center center'38}}39animate={{40rotateZ: isTop ? 0 : rotation,41translateX: Math.random() < 0.5 ? x : -x,42opacity: isTop ? [0, 1] : 0.8,43translateY: isTop ? [30, Math.random() < 0.5 ? y : -y] : Math.random() < 0.5 ? y : -y,44transition: {45duration: 0.546}47}}48initial={isTop ? { rotateZ: 0 } : { rotateZ: rotation }}49>50<div className="relative h-full w-full overflow-hidden rounded-3xl">51<Image52src={image}53alt={`stacked-card-${i}`}54height={1080}55width={1920}56className="h-full w-full object-cover"57priority={isTop}58/>59</div>60</motion.div>61);62})}63</div>64);65};6667export default ImagePile;
Usage
1<ImagePile2images={[3'https://images.unsplash.com/photo-1731770241468-8337b047749f?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',4'https://images.unsplash.com/photo-1728993559783-f657d4177c6b?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',5'https://images.unsplash.com/photo-1638392436949-3e584046314a?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',6'https://images.unsplash.com/photo-1726880066148-fdc1ceba7343?q=80&w=3876&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'7]}8/>
βοΈ Got a question or feedback?
Feel free to reach out!