Alexandre PUJOL
Alexandre PUJOL

Reputation: 150

framer motion : different animation for mobile and desktop

Trying to make a different animation when on mobile or on desktop, to do so I'm using a useMediaQueryHoook and changing the variant in function of it. But the init animation seems to always assume that I'm on desktop. I guess because the useMediaQueryHook doesn't have time to actualise before the anim is launch. How can I deal with that issue ?

Btw I'm on nextjs :)

Here is my code :

  const onMobile = useMediaQuery("(min-width : 428px)");

  const wishCardVariant = {
    hidden: (onMobile) => ({
      opacity: 0,
      y: onMobile ? "100%" : 0,
      x: onMobile ? 0 : "100%",
      transition,
    }),
    visible: (onMobile) => ({
      opacity: 1,
      x: 0,
      y: 0,
    }),
  };

here is the hook :

import react, { useState, useEffect } from "react";

export default function useMediaQuery(query) {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => {
      setMatches(media.matches);
    };
    media.addListener(listener);
    return () => media.removeListener(listener);
  }, [matches, query]);

  return matches;
}

Upvotes: 4

Views: 1713

Answers (2)

Aga
Aga

Reputation: 1394

Different text style based on device, mobile or desktop.

First check device isMobile.
Then apply style with conditional operator isMobile ? {} : {}

 const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

 return (
  ...
         <motion.h2 
              className="absolute top-1/2 left-1/2 text-white text-2xl font-bold whitespace-nowrap p-2"
              initial={isMobile ? false : { 
                background: "transparent"
              }}
              style={isMobile ? {
                background: "rgba(0, 0, 0, 0.5)",
              } : { 
                transformOrigin: "center center",
                x: "-50%",
                y: "-50%"
              }}
              variants={{
                hover: { 
                  scale: 1.2,
                  background: "rgba(0, 0, 0, 0.5)",
                  transition: { duration: 0.3 }
                }
              }}
            >
              {image.title}
            </motion.h2>   
 )

Upvotes: 0

Karel Suchomel
Karel Suchomel

Reputation: 31

You could try using useLayoutEffect. I had a similar issue, where I wanted to apply a different style based on device type, and this worked for me

export default function useMediaQuery(query: string) {
  const [matches, setMatches] = useState(false)

  useLayoutEffect(() => {
    const media = window.matchMedia(query)
    if (media.matches !== matches) {
      setMatches(media.matches)
    }
    const listener = () => {
      setMatches(media.matches)
    }
    media.addEventListener('change', listener)
    return () => media.removeEventListener('change', listener)
  }, [matches, query])

  return matches
}

Upvotes: 0

Related Questions