Gallery Grid
Free Gallery React component — GalleryGridCard. MIT licensed, copy-paste ready for Next.js and Tailwind CSS.
Album preview with title, subtitle, and a three-cell photo grid — last cell shows a +N overflow count. Portfolio and gallery index pages.
Preview
Summer Collection
24 photos · Jun 2026



+21
Setup
How to use
Free for personal and commercial use. No UI attribution required. Include the MIT copyright notice when copying component source into your project. Read the MIT license.
- 1
Run in your terminal:
$npm install clsx tailwind-merge lucide-react - 2
Copy
lib/cn.tsbelow. Skip if you already havecn(). - 3
Copy the code below and create
components/gallery/gallery-grid-card.tsxin your project. - 4
Import and render:
Exampleimport { GalleryGridCard } from "@/components/gallery/gallery-grid-card";
lib/cn.ts
import { type ClassValue, clsx } from "clsx";import { twMerge } from "tailwind-merge";export function cn(...inputs: ClassValue[]) {return twMerge(clsx(inputs));}
components/gallery/gallery-grid-card.tsx
import {forwardRef,type ComponentPropsWithoutRef,type ReactNode,} from "react";import Image from "next/image";import { cn } from "@/lib/cn";import { Sun } from "lucide-react";export type GalleryGridCardProps = Readonly<{title?: string;subtitle?: string;count?: string | number;images?: string[];overlayText?: string;icon?: ReactNode;} & ComponentPropsWithoutRef<"div">>;// Production-ready Gallery Grid component — styled with Tailwind CSS.export const GalleryGridCard = forwardRef<HTMLDivElement, GalleryGridCardProps>(({className,title = "Summer Collection",subtitle = "Jun 2026",count = "24 photos",images = ["/background5.webp", "/background1.webp", "/wallpaper-11.png"],overlayText = "+21",icon,...props},ref,) => {return (<divref={ref}data-slot="gallery-grid-card"className={cn("w-72 overflow-hidden rounded-2xl border border-neutral-100 bg-white font-sans shadow-lg",className,)}{...props}><div className="flex items-center justify-between p-3 pb-2"><div><h3 className="text-sm font-semibold text-neutral-900">{title}</h3><p className="text-[10px] text-neutral-400">{count} · {subtitle}</p></div>{icon ?? <Sun className="text-neutral-500" size={16} />}</div>{/* Grid */}<div className="grid grid-cols-3 gap-1 px-3 pb-3">{/* Main large image */}<div className="relative col-span-2 row-span-2 aspect-square overflow-hidden rounded-xl"><Imagesrc={images[0]}alt={title}fillsizes="288px"className="object-cover transition-transform duration-500 hover:scale-105"/></div>{/* Small image 1 */}<div className="relative aspect-square overflow-hidden rounded-xl"><Imagesrc={images[1]}alt={title}fillsizes="96px"className="object-cover"/></div>{/* Small image 2 with overlay */}<div className="relative aspect-square overflow-hidden rounded-xl"><Imagesrc={images[2]}alt={title}fillsizes="96px"className="object-cover"/><div className="absolute inset-0 flex items-center justify-center bg-black/50"><span className="text-xs font-semibold text-white">{overlayText}</span></div></div></div></div>);},);GalleryGridCard.displayName = "GalleryGridCard";