Masonry Grid
Masonry Grid is the perfect solution for dynamic, Pinterest-style layouts that adapt beautifully to any screen size. Built with React, Next.js, and Tailwind CSS, this grid intelligently arranges elements into an optimized, gap-free layout, making it ideal for image galleries, portfolios, and product listings. Say goodbye to rigid rows and columns—Masonry Grid ensures your content flows seamlessly, no matter the shape or size. Fully responsive, lightweight, and easy to customize, this component helps you create visually stunning layouts without the hassle. Get started with StackBits and elevate your UI with effortless grid magic! 🚀
Preview
Follow below steps 👇🏻
Install dependencies
1npm i framer-motion tailwindcss-animate
Component
Create a file masonry-grid.tsx in your components folder and paste this code
1'use client';23import React, { useState } from 'react';4import { motion } from 'framer-motion';5import Image from 'next/image';67interface MasonryGridProps {8items: { image: string; title: string; description: string }[];9columns?: number | undefined;10}1112const MasonryGrid: React.FC<MasonryGridProps> = ({ items, columns = undefined }) => {13const [imagesLoaded, setImagesLoaded] = useState<{ [key: string]: boolean }>({});1415if (!items || items.length === 0) {16return <div className="text-center p-4">No items to display</div>;17}1819return (20<div21style={{22columns: columns23}}24className={`${25!columns && 'columns-1 sm:columns-2 md:columns-3 lg:columns-4'26} gap-2 overflow-y-auto p-3 w-full`}27>28{items.map((item, index) => {29// Calculate row number based on screen size and index30const getColumnCount = () => {31if (typeof window === 'undefined') return 1;32const width = window.innerWidth;33if (width >= 1024) return 4; // lg34if (width >= 768) return 3; // md35if (width >= 640) return 2; // sm36return 1;37};3839const columnCount = getColumnCount();40const rowIndex = Math.floor(index / columnCount);4142return (43<motion.div44key={index}45className="break-inside-avoid mb-4 relative group rounded-xl overflow-hidden p-1 border-[1px] border-transparent hover:border-[1px] hover:border-neutral-800"46initial={{ opacity: 0, y: 20 }}47animate={{48opacity: 1,49y: 0,50transition: {51duration: 0.5,52delay: rowIndex * 0.1,53ease: 'easeOut'54}55}}56whileHover={{ scale: 1.05, rotateZ: 1 }}57>58<div className="relative">59<div className="relative w-full flex gap-1 flex-col items-start justify-start">60{!imagesLoaded[item.image] && (61<div className="absolute inset-0 w-full h-[300px] bg-neutral-500/50 animate-pulse rounded-lg" />62)}63<Image64src={item.image}65alt={item.title}66width={400}67height={300}68className={`${69!imagesLoaded[item.image] ? 'opacity-0' : 'opacity-100'70} w-full h-auto transition-transform duration-300 rounded-lg`}71sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1024px) 33vw, 25vw"72onLoad={() => {73setImagesLoaded((prev) => ({ ...prev, [item.image]: true }));74}}75onError={() => {76console.error(`Error loading image: ${item.image}`);77setImagesLoaded((prev) => ({ ...prev, [item.image]: true }));78}}79/>80{imagesLoaded[item.image] && (81<div className="w-full">82<h3 className="text-sm font-medium">{item.title}</h3>83<p className="mt-0 text-xs text-neutral-500 line-clamp-2 overflow-hidden">84{item.description}85</p>86</div>87)}88</div>89</div>90</motion.div>91);92})}93</div>94);95};9697export default MasonryGrid;
Usage
1<MasonryGrid2items={[3{4title: 'Urban Skyline',5image:6'https://images.unsplash.com/photo-1718563552473-2d97b224e801?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw1fHx8ZW58MHx8fHx8',7description:8'A breathtaking view of a modern cityscape with towering skyscrapers illuminated at dusk.'9},10{11title: 'Mountain Retreat',12image:13'https://images.unsplash.com/photo-1735317461815-1a0ba64e9a56?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHwyMXx8fGVufDB8fHx8fA%3D%3D',14description:15'A serene cabin nestled in the heart of towering mountains, perfect for a peaceful getaway.'16},17{18title: 'Forest Wander',19image:20'https://images.unsplash.com/photo-1502082553048-f009c37129b9?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',21description:22'A misty trail winding through a dense, enchanting forest filled with lush greenery.'23},24{25title: 'Serene Lake',26image:27'https://images.unsplash.com/photo-1504384308090-c894fdcc538d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',28description:29'A tranquil lake reflecting the golden hues of the sunset, surrounded by peaceful nature.'30},31{32title: 'Golden Hour',33image:34'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',35description:36'A mesmerizing sunset casting a warm glow over the ocean, creating a dreamlike atmosphere.'37},38{39title: 'Coastal Vibes',40image:41'https://images.unsplash.com/photo-1493558103817-58b2924bce98?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',42description:43'Crystal-clear waves crashing against a sandy shore, offering a perfect beach escape.'44},45{46title: 'Night Lights',47image:48'https://images.unsplash.com/photo-1502933691298-84fc14542831?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8d2F0ZXIlMjBzcG9ydHxlbnwwfHwwfHx8MA%3D%3D',49description:50'A dazzling city skyline at night, with vibrant lights illuminating the urban landscape.'51},52{53title: 'Rustic Charm',54image:55'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',56description:57'A cozy wooden cabin with a warm, inviting atmosphere set in a countryside setting.'58}59]}60></MasonryGrid>
⭐️ Got a question or feedback?
Feel free to reach out!