Introducing Aceternity UI Pro - 70+ premium component packs and templates to build amazing websites.
Logo

Focus Cards

Hover over the card to focus on it, blurring the rest of the cards.

Open in
Forest Adventure
Forest Adventure
Valley of life
Valley of life
Sala behta hi jayega
Sala behta hi jayega
Camping is for pros
Camping is for pros
The road not taken
The road not taken
The First Rule
The First Rule

Installation

Install dependencies

npm i motion clsx tailwind-merge @tabler/icons-react

Add util file

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

Copy the source code

components/ui/focus-cards.tsx

"use client";
 
import React, { useState } from "react";
import { cn } from "@/lib/utils";
 
export const Card = React.memo(
  ({
    card,
    index,
    hovered,
    setHovered,
  }: {
    card: any;
    index: number;
    hovered: number | null;
    setHovered: React.Dispatch<React.SetStateAction<number | null>>;
  }) => (
    <div
      onMouseEnter={() => setHovered(index)}
      onMouseLeave={() => setHovered(null)}
      className={cn(
        "rounded-lg relative bg-gray-100 dark:bg-neutral-900 overflow-hidden h-60 md:h-96 w-full transition-all duration-300 ease-out",
        hovered !== null && hovered !== index && "blur-sm scale-[0.98]"
      )}
    >
      <img
        src={card.src}
        alt={card.title}
        className="object-cover absolute inset-0"
      />
      <div
        className={cn(
          "absolute inset-0 bg-black/50 flex items-end py-8 px-4 transition-opacity duration-300",
          hovered === index ? "opacity-100" : "opacity-0"
        )}
      >
        <div className="text-xl md:text-2xl font-medium bg-clip-text text-transparent bg-gradient-to-b from-neutral-50 to-neutral-200">
          {card.title}
        </div>
      </div>
    </div>
  )
);
 
Card.displayName = "Card";
 
type Card = {
  title: string;
  src: string;
};
 
export function FocusCards({ cards }: { cards: Card[] }) {
  const [hovered, setHovered] = useState<number | null>(null);
 
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-10 max-w-5xl mx-auto md:px-8 w-full">
      {cards.map((card, index) => (
        <Card
          key={card.title}
          card={card}
          index={index}
          hovered={hovered}
          setHovered={setHovered}
        />
      ))}
    </div>
  );
}

Props

ComponentPropTypeDescription
CardcardCardThe card object containing title and src properties
CardindexnumberThe index of the card in the array
Cardhoverednumber | nullThe index of the currently hovered card, or null if no card is hovered
CardsetHoveredReact.Dispatch<React.SetStateAction<number | null>>Function to update the hovered state
FocusCardscardsCard[]An array of Card objects to be rendered

Build websites faster and 10x better than your competitors with Aceternity UI Pro

With the best in class components and templates, stand out from the crowd and get more attention to your website. Trusted by founders and entrepreneurs from all over the world.

Go Pro
Manu is the man! He is the best front-end developer I have worked with. He took the requirements and quite literally ran with them. We are super happy with the result and product we go...

John Shahawy

Founder at Rogue and Moonbeam

A product by Aceternity
Building in public at @mannupaaji