Search code examples
cssreactjstailwind-css

React and Tailwind: Hover effect on one card causes both cards to expand, even though they have independent hover states


I am trying to create two cards in React, each with an independent hover effect. When I hover over Card 1, I want only Card 1 to expand, and when I hover over Card 2, I want only Card 2 to expand. However, when I hover over either card, both cards expand.

Here is the code I have:

import React, { useState } from "react";
import card1 from "../assets/Logos/card1.gif";
import card2 from "../assets/Logos/card2.gif";

const Demo = () => {
  // Independent hover states for each card
  const [isHoveredCard1, setIsHoveredCard1] = useState(false);
  const [isHoveredCard2, setIsHoveredCard2] = useState(false);

  return (
    <div className="bg-black grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-36 py-14 px-24">
      {/* Card 1 */}
      <div
        className="bg-black px-6 py-10 rounded-3xl flex flex-col justify-center transition-all duration-500 ease-in-out"
        onMouseEnter={() => setIsHoveredCard1(true)}
        onMouseLeave={() => setIsHoveredCard1(false)}
      >
        <img className="w-16" src={card1} alt="" />
        <h1 className="text-[#7670EA] font-Poppins-Medium text-xl">
          Creativity With Purpose:
        </h1>
        <div
          className={`overflow-hidden transition-all duration-500 ease-in-out ${
            isHoveredCard1 ? "max-h-40" : "max-h-0"
          }`}
        >
          <p className="text-white pt-4">
            We bring ideas to life, crafting innovative and meaningful
            narratives that resonate with your audience.
          </p>
        </div>
      </div>

      {/* Card 2 */}
      <div
        className="bg-black px-6 py-10 rounded-3xl flex flex-col justify-center transition-all duration-500 ease-in-out"
        onMouseEnter={() => setIsHoveredCard2(true)}
        onMouseLeave={() => setIsHoveredCard2(false)}
      >
        <img className="w-16" src={card2} alt="" />
        <h1 className="text-[#F43C3C] font-Poppins-Medium text-xl">
          Client-Service Focused:
        </h1>
        <div
          className={`overflow-hidden transition-all duration-500 ease-in-out ${
            isHoveredCard2 ? "max-h-40" : "max-h-0"
          }`}
        >
          <p className="text-white pt-4">
            Your vision is our mission. We partner with you to create strategies
            that elevate your brand.
          </p>
        </div>
      </div>
    </div>
  );
};

export default Demo;

You can find the output image in this link: https://www.filemail.com/d/guqzjuttbyuvzvu


Solution

  • I would extract the card into its own component so that each card has its own independent state.

    i.e. Card component:

    const Card = ({ title, description, icon, titleColor }) => {
      const [isHovered, setIsHovered] = useState(false);
      
      return (
        <div
          className="bg-black px-6 py-10 rounded-3xl flex flex-col justify-center transition-all duration-500 ease-in-out"
          onMouseEnter={() => setIsHovered(true)}
          onMouseLeave={() => setIsHovered(false)}
        >
          {/* Card content */}
        </div>
      );
    };
    

    Rendering card:

          <Card 
            title="Creativity With Purpose:"
            description="We bring ideas to life..."
            titleColor="text-[#7670EA]"
            icon={card1}
          />
          <Card 
            title="Client-Service Focused:"
            description="Your vision is our mission..."
            titleColor="text-[#F43C3C]"
            icon={card2}
          />