Search code examples
reactjsframer-motionscrolltrigger

Pinning and unpinning elements on scroll with Framer Motion (ScrollTrigger)


I am new to Framer Motion and I am trying to recreate ScrollTrigger's functionality of pinning and unpinning elements on scroll. In the example I have working, the box unpins when component <Two /> enters the viewport, but when you scroll back up to re-pin it, you get a slight stutter, even with the layout parameter set.

Is there a better way to do this with Framer Motion?

Sandbox here


Solution

  • The slight stutter you're experiencing when scrolling back up to re-pin the box is likely due to the way you're updating the position of the box with top: pinBox && scrollY. This expression is causing the box to jump to the current scroll position whenever pinBox changes from false to true. You can use useTransform hook in this kind of situation.

     const { scrollY } = useScroll();
     const [pinBox, setPinBox] = useState(true);
    
     const boxY = useTransform(
        scrollY,
        [0, window.innerHeight],
        [0, window.innerHeight]
      );
    
    

    And apply following changes inside motion.div component's style prop

    <motion.div
            layout
            style={{
              position: "absolute",
              top: pinBox ? boxY : "auto",
              bottom: pinBox ? "auto" : 0,
              left: "50%",
              width: "100px",
              height: "100px",
              backgroundColor: "red",
              x: "-50%"
            }}
          />
    
    

    This should fix the stutter.