Search code examples
cssreactjstailwind-css

Grayscale filter transition dont work in tailwind


I have my card images and I'm trying to make it so that when I hover over the image it goes from black and white to color. I've tried many ways but I can't seem to get it to work, I don't know what it could be, if anyone has any ideas it would be a great help, thank you very much!

    const WatchFilm = ({ movie }) => {
                                                                                                                                                                                               
     const [isGrayscale, setIsGrayscale] = useState(true); 
     const genreName =
       movie.genres.length > 0 ? movie.genres[0].name : "Sin Género";

  const animationVariants = {
   hidden: { opacity: 0, scale: 0.8 },
    visible: { opacity: 1, scale: 1 },
 };

  useEffect(() => {
    setIsGrayscale(true); // Inicialmente, la imagen se muestra en grayscale
  }, [
    movie.cover, // Dependencia para el efecto de grayscale

  ]);

 return (
<motion.div
  className="relative cursor-pointer bg-blue-700 rounded-lg overflow-hidden transition-all duration-500 hover:bg-gradient-to-r hover:from-blue-500 hover:to-purple-600 w-64 mx-2 my-12 transform hover:scale-110"
  initial="hidden"
  animate="visible"
  variants={animationVariants}
  transition={{ duration: 0.5 }}
>
  <img
    className={`h-96 w-full object-cover transition-transform duration-300 hover:scale-105 ${
      isGrayscale ? "filter filter-grayscale-100" : "grayscale"
    }`}
    src={movie.cover}
    alt={movie.title}
    onMouseEnter={() => setIsGrayscale(false)} // Quitar grayscale al pasar el ratón
    onMouseLeave={() => setIsGrayscale(true)} // Volver a poner grayscale al salir el ratón
  />
  <div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-25 transition-opacity duration-300 hover:opacity-100" />
  <div className="absolute bottom-0 left-0 w-full bg-black bg-opacity-60 p-2 text-white text-center transition-all duration-500">
    <h2 className="text-md sm:text-lg font-light font-afacadFlux">
      {genreName}
    </h2>
  </div>
</motion.div>

); };`


Solution

    1. I think you do not need to use a state to control the color transition. You have the option to apply the classes grayscale hover:grayscale-0 to your image as seen on the documentation here.
    2. I have also removed <div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-25 transition-opacity duration-300 hover:opacity-100" /> from your code as it appears to affect the grayscale-to-color transition.

    Here is the final piece code

    const WatchFilm = ({ movie }) => {
      const genreName = movie.genres.length > 0 ? movie.genres[0].name : "Sin Género";
    
      const animationVariants = {
        hidden: { opacity: 0, scale: 0.8 },
        visible: { opacity: 1, scale: 1 },
      };
    
      return (
        <motion.div
          className="relative cursor-pointer bg-blue-700 rounded-lg overflow-hidden transition-all duration-500 hover:bg-gradient-to-r hover:from-blue-500 hover:to-purple-600 w-64 mx-2 my-12 transform hover:scale-110"
          initial="hidden"
          animate="visible"
          variants={animationVariants}
          transition={{ duration: 0.5 }}
        >
           <img
            className={"h-96 w-full object-cover transition-transform duration-300 hover:scale-105 filter grayscale hover:grayscale-0"}
            src={movie.cover}
            alt={movie.title}
          />
          <div className="absolute bottom-0 left-0 w-full bg-black bg-opacity-60 p-2 text-white text-center transition-all duration-500">
            <h2 className="text-md sm:text-lg font-light font-afacadFlux">
              {genreName}
            </h2>
          </div>
        </motion.div>
      );
    };