tumtarts
tumtarts

Reputation: 11

CSS Transition doesn't work when a class is added dynamically in Next JS project

I have a simple Next.js project running Tailwind for styling and ran into an issue when I using the globals.css file for a more complicated CSS (not tailwind) styling I had to do for a component.

Here's is the Code Sandbox for a better visualization https://codesandbox.io/p/sandbox/muddy-pine-hx86sf but essentially I am trying to accomplish this transition when I click on a list item.

However in the Sandbox and in my Next.js local development, this transition is simply skipped and the new background color is applied immediately instead of the transition playing out.

I am not sure if I am misunderstanding how CSS transitions work or if this has something to do with Next JS or a lack of understanding on dynamically applying CSS to elements.

  1. Tried using Firefox DevTools to manually apply the class that changes the background position active-location-item and this caused the transition to work.
  2. Tried using different CSS selectors to no avail (same issue of no transition playing).
  3. Verified that the class is getting applied in DevTools when the item is clicked.

Any help on this would be appreciated!

Upvotes: 0

Views: 985

Answers (1)

Wongjn
Wongjn

Reputation: 24408

The problem is that you are returning a new component within Modal. Every time the state changes, the const LocationView is initialized over again. Since it is inside Modal, React sees LocationView as a completely new component since it is not the same reference on rerender and will remount it, causing no transitions to run.

Instead, return the JSX directly:

const { useState } = React;

const Modal = () => {
  const [activeLocation, setActiveLocation] = useState("");

  const handleLocationClick = () => {
    setActiveLocation("Example");
  };

  return (
    <div className="flex flex-col w-[600px]">
      <div className="flex flex-col text-hsr-dark font-medium grow">
        <ul className="list-disc list-inside">
          <li
            onClick={handleLocationClick}
            className={`${
              activeLocation === "Example" ? "active-location-item" : ""
            } location-item cursor-pointer text-2xl p-10 outline outline-2 outline-transparent  mb-1`}
          >
            Example
          </li>
        </ul>
      </div>
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('app')).render(<Modal/>);

tailwind.config = {
  theme: {
    extend: {
      colors: {
        "hsr-dark": "#404040",
        "hsr-grey": "#BFBFBF",
      },
    },
  },
};
<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.3.2"></script>

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

<style type="text/tailwindcss">
:root {
  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;
}

.location-item {
  background-image: linear-gradient(
    to right,
    theme("colors.hsr-dark") 50%,
    theme("colors.hsr-grey") 50%
  );
  background-size: 200% 100%;
  background-position: right bottom;
  transition: all 0.75s;
}

.active-location-item {
  background-position: left bottom;
}
</style>

Upvotes: 0

Related Questions