Problem in Hover Animation in a ReactJS Component

19 Views Asked by At

So, I was trying to clone the website of Rivian, I had a component which contains 2 boxes, and they have some hover animations similar to the one seen on the websites. The animation on the left box is working perfectly fine that it the right box shrinks a little to the right giving space for box1 to expand.But the same thing is not working for box2. Here's the code:

Configurator.jsx

import "./configurator.css";
const Configurator = () => {
  return (
    <div style={{ width: "100%", backgroundColor: "#fff", height: "90vh" }}>
      <div
        className="grid grid-cols-2 gap-7 pt-20 "
        style={{ height: "30vh", marginBottom: "5vh" }}
      >
        <div className="flex justify-end">
          <h1 className="text-5xl">
            Vehicles made for the <br />
            planet
          </h1>
        </div>
        <div>
          <h3 className="text-xl">
            Whether taking families on new adventures or <br /> electrifying
            fleets at scale, our vehicles all share a <br /> common goal —
            preserving the natural world for <br /> generations to come.
          </h3>
        </div>
      </div>

      <div
        className="grid grid-cols-2 gap-7 px-0 border-2
        mx-4 overflow-hidden"
        style={{ height: "40vh", marginBottom: "5vh" }}
      >
        <div
          className="h-30 w-full relative box1"
          style={{ backgroundColor: "#f2f2f2" }} 
        >
          <div className="h-full w-full box-content">
            <h3 className="absolute top-4 left-4">
              R1T | Up to 410 miles of range
            </h3>
            <div className="absolute top-1/5 left-20 right-10 flex justify-center">
              <img
                className="aspect-[4/3]"
                src="src\assets\asset 2.png"
                alt=""
              />
            </div>
            <div className="absolute bottom-0 flex justify-end w-full pb-6 px-6 gap-4">
              <button className="border-2 border-black rounded-3xl py-3 px-8">
                Configure
              </button>
              <button className="text-white border-2 border-black rounded-3xl bg-black py-3 px-6">
                Shop Available
              </button>
            </div>
          </div>
        </div>

        <div
          className="h-30 w-full relative box2"
          style={{ backgroundColor: "#f2f2f2" }}
        >
          <div className="h-full w-full box-content">
            <h3 className="absolute top-4 left-4">
              R1T | Up to 410 miles of range
            </h3>
            <div className="absolute top-1/5 left-20 right-10 flex justify-center">
              <img
                className="aspect-[4/3]"
                src="src\assets\asset 2.png"
                alt=""
              />
            </div>
            <div className="absolute bottom-0 flex justify-end w-full pb-6 px-6 gap-4">
              <button className="border-2 border-black rounded-3xl py-3 px-8">
                Configure
              </button>
              <button className="text-white border-2 border-black rounded-3xl bg-black py-3 px-6">
                Shop Available
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Configurator;

configurator.css

.container {
  display: flex;
  height: 80vh;
  width: 100%;
}

.box1,
.box2 {
  transition: transform 0.5s ease-in-out;
}

.box1:hover,
.box2:hover {
  transform: scaleX(1.1);
}

.box1 .box-content {
  transition: transform 0.5s ease-in-out;
}
.box2 .box-content {
  transition: transform 0.5s ease-in-out;
}

.box1:hover .box-content {
  transform: scaleX(0.9091);
}

.box1:hover ~ .box2 {
  transform: translateX(3%);
}

.box2:hover .box-content {
  transform: scaleX(0.9091);
}

.box2:hover ~ .box1 {
  transform: translateX(3%);
}

I tried playing around with some CSS and some properties of the component itself, but was not able to get it working properly, the box2 expands but the box1 does not shrinks maintaining the gap between them. I want the two boxes to work the exact same way as it does on Rivian

1

There are 1 best solutions below

0
Wongjn On BEST ANSWER

Your use of the subsequent-sibling combinator, ~, would not match box1 when box2 is hovered, since as the name suggests, the combinator only matches sibling elements after the selector that comes before it.

Instead, you could consider using :has() on the .box1 element, to match it when there is a subsequent element that matches .box2:hover.

You may also consider inverting the translateX() to have it go to the left, mirroring the effect:

.box1:has(~ .box2:hover) {
  transform: translateX(-3%);
}

const Configurator = () => {
  return (
    <div style={{ width: "100%", backgroundColor: "#fff", height: "90vh" }}>
      <div
        className="grid grid-cols-2 gap-7 pt-20 "
        style={{ height: "30vh", marginBottom: "5vh" }}
      >
        <div className="flex justify-end">
          <h1 className="text-5xl">
            Vehicles made for the <br />
            planet
          </h1>
        </div>
        <div>
          <h3 className="text-xl">
            Whether taking families on new adventures or <br /> electrifying
            fleets at scale, our vehicles all share a <br /> common goal —
            preserving the natural world for <br /> generations to come.
          </h3>
        </div>
      </div>

      <div
        className="grid grid-cols-2 gap-7 px-0 border-2
        mx-4 overflow-hidden"
        style={{ height: "40vh", marginBottom: "5vh" }}
      >
        <div
          className="h-30 w-full relative box1"
          style={{ backgroundColor: "#f2f2f2" }} 
        >
          <div className="h-full w-full box-content">
            <h3 className="absolute top-4 left-4">
              R1T | Up to 410 miles of range
            </h3>
            <div className="absolute top-1/5 left-20 right-10 flex justify-center">
              <img
                className="aspect-[4/3]"
                src="src\assets\asset 2.png"
                alt=""
              />
            </div>
            <div className="absolute bottom-0 flex justify-end w-full pb-6 px-6 gap-4">
              <button className="border-2 border-black rounded-3xl py-3 px-8">
                Configure
              </button>
              <button className="text-white border-2 border-black rounded-3xl bg-black py-3 px-6">
                Shop Available
              </button>
            </div>
          </div>
        </div>

        <div
          className="h-30 w-full relative box2"
          style={{ backgroundColor: "#f2f2f2" }}
        >
          <div className="h-full w-full box-content">
            <h3 className="absolute top-4 left-4">
              R1T | Up to 410 miles of range
            </h3>
            <div className="absolute top-1/5 left-20 right-10 flex justify-center">
              <img
                className="aspect-[4/3]"
                src="src\assets\asset 2.png"
                alt=""
              />
            </div>
            <div className="absolute bottom-0 flex justify-end w-full pb-6 px-6 gap-4">
              <button className="border-2 border-black rounded-3xl py-3 px-8">
                Configure
              </button>
              <button className="text-white border-2 border-black rounded-3xl bg-black py-3 px-6">
                Shop Available
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('app')).render(<Configurator/>);
.container {
  display: flex;
  height: 80vh;
  width: 100%;
}

.box1,
.box2 {
  transition: transform 0.5s ease-in-out;
}

.box1:hover,
.box2:hover {
  transform: scaleX(1.1);
}

.box1 .box-content {
  transition: transform 0.5s ease-in-out;
}
.box2 .box-content {
  transition: transform 0.5s ease-in-out;
}

.box1:hover .box-content {
  transform: scaleX(0.9091);
}

.box1:hover ~ .box2 {
  transform: translateX(3%);
}

.box2:hover .box-content {
  transform: scaleX(0.9091);
}

.box1:has(~ .box2:hover) {
  transform: translateX(-3%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.tailwindcss.com/3.4.1"></script>

<div id="app"></div>