Installation
Install dependencies
npm install framer-motion react-iconsCopy and paste the following code into your project.
"use client";
import { motion } from "framer-motion";
import { createElement } from "react";
interface Logo {
id: string;
name: string;
logo?: string;
icon?: React.ElementType;
url?: string;
}
interface CustomerLogosWallProps {
title?: string;
description?: string;
logos: Logo[];
columns?: 3 | 4 | 5 | 6;
grayscale?: boolean;
className?: string;
}
export function CustomerLogosWall({
title = "Trusted by industry leaders",
description = "Join thousands of companies that rely on our platform",
logos,
columns = 6,
grayscale = true,
className = "",
}: CustomerLogosWallProps) {
const gridCols = {
3: "grid-cols-2 sm:grid-cols-3",
4: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4",
5: "grid-cols-2 sm:grid-cols-3 md:grid-cols-5",
6: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6",
}[columns];
return (
<section className={`w-full bg-white py-16 dark:bg-black ${className}`}>
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
{/* Header */}
{(title || description) && (
<div className="mb-12 text-center">
{title && (
<h2 className="mb-3 text-2xl font-bold text-zinc-900 dark:text-white sm:text-3xl">
{title}
</h2>
)}
{description && (
<p className="text-base text-zinc-600 dark:text-zinc-400">
{description}
</p>
)}
</div>
)}
{/* Logos Grid */}
<div className={`grid gap-8 ${gridCols}`}>
{logos.map((logo, index) => (
<motion.div
key={logo.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.05, duration: 0.4 }}
className="group relative flex items-center justify-center"
>
{logo.url ? (
<a
href={logo.url}
target="_blank"
rel="noopener noreferrer"
className="flex h-20 w-full items-center justify-center rounded-xl border border-zinc-200 bg-white p-6 transition-all duration-300 hover:border-zinc-300 hover:shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:hover:border-zinc-700"
>
{logo.icon ? (
createElement(logo.icon, {
className: `h-10 w-10 transition-all duration-300 ${
grayscale
? "grayscale opacity-60 group-hover:grayscale-0 group-hover:opacity-100"
: "opacity-80 group-hover:opacity-100"
}`,
})
) : (
<img
src={logo.logo}
alt={logo.name}
className={`h-full w-full object-contain transition-all duration-300 ${
grayscale
? "grayscale opacity-60 group-hover:grayscale-0 group-hover:opacity-100"
: "opacity-80 group-hover:opacity-100"
}`}
/>
)}
</a>
) : (
<div className="flex h-20 w-full items-center justify-center rounded-xl border border-zinc-200 bg-white p-6 transition-all duration-300 hover:border-zinc-300 hover:shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:hover:border-zinc-700">
{logo.icon ? (
createElement(logo.icon, {
className: `h-10 w-10 transition-all duration-300 ${
grayscale
? "grayscale opacity-60 group-hover:grayscale-0 group-hover:opacity-100"
: "opacity-80 group-hover:opacity-100"
}`,
})
) : (
<img
src={logo.logo}
alt={logo.name}
className={`h-full w-full object-contain transition-all duration-300 ${
grayscale
? "grayscale opacity-60 group-hover:grayscale-0 group-hover:opacity-100"
: "opacity-80 group-hover:opacity-100"
}`}
/>
)}
</div>
)}
</motion.div>
))}
</div>
{/* Bottom Text */}
<div className="mt-12 text-center">
<p className="text-sm text-zinc-500 dark:text-zinc-500">
And many more companies worldwide
</p>
</div>
</div>
</section>
);
}Features
- ✅ Flexible columns - Choose 3, 4, 5, or 6 column layouts
- ✅ Grayscale effect - Optional grayscale with color on hover
- ✅ Hover animations - Smooth opacity and shadow transitions
- ✅ Clickable logos - Optional links to company websites
- ✅ Responsive grid - Adapts to all screen sizes
- ✅ Light/dark mode - Full theme support
- ✅ Staggered animation - Sequential logo appearance
- ✅ Clean borders - Subtle card borders
- ✅ TypeScript support - Full type safety
Usage
Basic Usage with React Icons (Recommended)
import CustomerLogosWall from "@/components/ui/customer-logos-wall";
import {SiVercel, SiNextdotjs, SiStripe} from "react-icons/si";
const logos = [
{
id: "1",
name: "Vercel",
icon: SiVercel,
url: "https://vercel.com",
},
{
id: "2",
name: "Next.js",
icon: SiNextdotjs,
url: "https://nextjs.org",
},
// ... more logos
];
export default function Page() {
return <CustomerLogosWall logos={logos} />;
}With Image URLs
const logos = [
{
id: "1",
name: "Company Name",
logo: "/logos/company.png",
url: "https://company.com",
},
// ... more logos
];4 Column Layout
<CustomerLogosWall logos={logos} columns={4} />Without Grayscale
<CustomerLogosWall logos={logos} grayscale={false} />With Custom Title
<CustomerLogosWall
title="Trusted by industry leaders"
description="Join thousands of companies worldwide"
logos={logos}
/>Without Header
<CustomerLogosWall title="" description="" logos={logos} />Props
CustomerLogosWallProps
| Prop | Type | Default | Description |
|---|---|---|---|
logos | Logo[] | Required | Array of logo objects |
title | string | "Trusted by industry leaders" | Section title |
description | string | "Join thousands of companies..." | Section description |
columns | 3 | 4 | 5 | 6 | 6 | Number of columns |
grayscale | boolean | true | Apply grayscale effect |
className | string | "" | Additional CSS classes |
Logo
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier |
name | string | Yes | Company name (for alt text) |
logo | string | No* | Logo image URL |
icon | React.ElementType | No* | React Icon component |
url | string | No | Company website URL |
*Either logo or icon must be provided
TypeScript Interface
interface Logo {
id: string;
name: string;
logo?: string; // Image URL
icon?: React.ElementType; // React Icon component
url?: string;
}
interface CustomerLogosWallProps {
title?: string;
description?: string;
logos: Logo[];
columns?: 3 | 4 | 5 | 6;
grayscale?: boolean;
className?: string;
}Use Cases
Perfect for:
- SaaS landing pages
- Homepage social proof
- About pages
- Partner pages
- Case study sections
- Footer sections
- Investor pages
- Press pages
Logo Sources
React Icons (Recommended)
The easiest way to add logos is using react-icons:
npm install react-iconsSimple Icons (Si) - 2000+ brand logos:
import {SiVercel, SiNextdotjs, SiStripe, SiGithub} from "react-icons/si";Font Awesome Brands (Fa) - Popular brands:
import {FaApple, FaMicrosoft, FaGoogle} from "react-icons/fa";Browse all icons: react-icons.github.io
Image URLs
If using custom logos:
Recommended Specs:
- Format: PNG or SVG
- Background: Transparent
- Size: 200x200px minimum
- Color: Full color (grayscale applied by component)
- Padding: Include some padding in the image itself
Tools:
- Remove backgrounds: remove.bg
- Resize images: squoosh.app
- Convert to SVG: vectorizer.ai
Customization
Change Card Height
// Modify the card height
className = "flex h-24 w-full items-center..."; // Changed from h-20 to h-24Change Gap Between Logos
// Modify the grid gap
<div className={`grid gap-12 ${gridCols}`}> {/* Changed from gap-8 to gap-12 */}Remove Borders
// Remove border classes
className =
"flex h-20 w-full items-center justify-center rounded-xl bg-white p-6...";
// Removed: border border-zinc-200Add Background Pattern
<section className="... relative">
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]" />
<div className="relative">{/* Content */}</div>
</section>Custom Hover Colors
// Change hover border color
className = "... hover:border-blue-300 dark:hover:border-blue-700";Add Logo Tooltips
<div className="group relative...">
<img ... />
<div className="absolute -top-10 left-1/2 -translate-x-1/2 rounded bg-zinc-900 px-2 py-1 text-xs text-white opacity-0 transition-opacity group-hover:opacity-100">
{logo.name}
</div>
</div>Infinite Scroll Version
// For a marquee/infinite scroll effect, use the infinite-scroll component
// Or implement with CSS animations
<div className="overflow-hidden">
<div className="animate-scroll flex gap-8">
{logos.map(logo => (...))}
{logos.map(logo => (...))} {/* Duplicate for seamless loop */}
</div>
</div>Common Patterns
With Section Divider
<CustomerLogosWall
logos={logos}
className="border-t border-zinc-200 dark:border-zinc-800"
/>Compact Version
<CustomerLogosWall
title=""
description=""
logos={logos}
columns={6}
className="py-8" // Reduced padding
/>Featured Partners
<CustomerLogosWall
title="Featured Partners"
description="Strategic partnerships that drive innovation"
logos={featuredLogos}
columns={4}
grayscale={false}
/>Footer Logos
<CustomerLogosWall
title="As seen in"
logos={pressLogos}
columns={5}
className="bg-zinc-50 dark:bg-zinc-900"
/>